diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 65dc4a6d39c..c0b9b72f57d 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -13,3 +13,4 @@ bb1ef4ee3d2c8cbf43a37d372325a7952be590b9 jdk7-b33 4b4f5fea8d7d0743f0c30d91fcd9bf9d96e5d2ad jdk7-b36 744554f5a3290e11c71cd2ddb1aff49e431f9ed0 jdk7-b37 cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38 +ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39 diff --git a/corba/.hgtags b/corba/.hgtags index baa91282f79..ae11865afed 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -13,3 +13,4 @@ ef6af34d75a7b44e77083f1d4ee47631fa09d3b4 jdk7-b31 0723891eb8d1c27e67c54163af0b4cea05a4e036 jdk7-b36 59d5848bdedebe91cc2753acce78911bcb4a66db jdk7-b37 08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38 +55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 15a4678d894..f7cd42cd696 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -13,3 +13,4 @@ b727c32788a906c04839516ae7443a085185a300 jdk7-b32 e91159f921a58af3698e6479ea1fc5818da66d09 jdk7-b36 9ee9cf798b59e7d51f8c0a686959f313867a55d6 jdk7-b37 d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38 +49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39 diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index efc6eb5223d..9673d78aba6 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2008 HS_MAJOR_VER=14 HS_MINOR_VER=0 -HS_BUILD_NUMBER=06 +HS_BUILD_NUMBER=07 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 998f39508e7..07879e32a8b 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -2615,7 +2615,8 @@ void MacroAssembler::cas_under_lock(Register top_ptr_reg, Register top_reg, Regi } } -void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, Register temp_reg, +void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, + Register temp_reg, Label& done, Label* slow_case, BiasedLockingCounters* counters) { assert(UseBiasedLocking, "why call this otherwise?"); @@ -2691,8 +2692,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place, mark_reg); or3(G2_thread, mark_reg, temp_reg); - casx_under_lock(mark_addr.base(), mark_reg, temp_reg, - (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + casn(mark_addr.base(), mark_reg, temp_reg); // If the biasing toward our thread failed, this means that // another thread succeeded in biasing it toward itself and we // need to revoke that bias. The revocation will occur in the @@ -2721,8 +2721,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R load_klass(obj_reg, temp_reg); ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg); or3(G2_thread, temp_reg, temp_reg); - casx_under_lock(mark_addr.base(), mark_reg, temp_reg, - (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + casn(mark_addr.base(), mark_reg, temp_reg); // If the biasing toward our thread failed, this means that // another thread succeeded in biasing it toward itself and we // need to revoke that bias. The revocation will occur in the @@ -2752,8 +2751,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R // bits in this situation. Should attempt to preserve them. load_klass(obj_reg, temp_reg); ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg); - casx_under_lock(mark_addr.base(), mark_reg, temp_reg, - (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + casn(mark_addr.base(), mark_reg, temp_reg); // Fall through to the normal CAS-based lock, because no matter what // the result of the above CAS, some thread must have succeeded in // removing the bias bit from the object's header. @@ -2815,8 +2813,10 @@ void MacroAssembler::casn (Register addr_reg, Register cmp_reg, Register set_reg // effect). -void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch, - BiasedLockingCounters* counters) { +void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, + Register Rbox, Register Rscratch, + BiasedLockingCounters* counters, + bool try_bias) { Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes()); verify_oop(Roop); @@ -2838,7 +2838,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Registe // Fetch object's markword ld_ptr(mark_addr, Rmark); - if (UseBiasedLocking) { + if (try_bias) { biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); } @@ -2881,7 +2881,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Registe ld_ptr (mark_addr, Rmark); // fetch obj->mark // Triage: biased, stack-locked, neutral, inflated - if (UseBiasedLocking) { + if (try_bias) { biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); // Invariant: if control reaches this point in the emitted stream // then Rmark has not been modified. @@ -2945,7 +2945,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Registe ld_ptr (mark_addr, Rmark); // fetch obj->mark // Triage: biased, stack-locked, neutral, inflated - if (UseBiasedLocking) { + if (try_bias) { biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); // Invariant: if control reaches this point in the emitted stream // then Rmark has not been modified. @@ -3039,7 +3039,9 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Registe bind (done) ; } -void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch) { +void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, + Register Rbox, Register Rscratch, + bool try_bias) { Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes()); Label done ; @@ -3050,7 +3052,7 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, Regis } if (EmitSync & 8) { - if (UseBiasedLocking) { + if (try_bias) { biased_locking_exit(mark_addr, Rscratch, done); } @@ -3077,7 +3079,7 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, Regis // I$ effects. Label LStacked ; - if (UseBiasedLocking) { + if (try_bias) { // TODO: eliminate redundant LDs of obj->mark biased_locking_exit(mark_addr, Rscratch, done); } diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 3cea450cc2c..1d735ade174 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -2220,9 +2220,13 @@ class MacroAssembler: public Assembler { // These set the icc condition code to equal if the lock succeeded // and notEqual if it failed and requires a slow case - void compiler_lock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch, - BiasedLockingCounters* counters = NULL); - void compiler_unlock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch); + void compiler_lock_object(Register Roop, Register Rmark, Register Rbox, + Register Rscratch, + BiasedLockingCounters* counters = NULL, + bool try_bias = UseBiasedLocking); + void compiler_unlock_object(Register Roop, Register Rmark, Register Rbox, + Register Rscratch, + bool try_bias = UseBiasedLocking); // Biased locking support // Upon entry, lock_reg must point to the lock record on the stack, diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 5881dd69be4..f134852e4d6 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -906,7 +906,7 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, // load next super to check if (UseCompressedOops) { - ld( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); + lduw( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); // Bump array pointer forward one oop add( Rtmp2, 4, Rtmp2 ); } else { diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index c02673b3efc..06af021d1fd 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -395,6 +395,7 @@ reg_class long_reg( R_G1H,R_G1, R_G3H,R_G3, R_G4H,R_G4, ); reg_class g1_regL(R_G1H,R_G1); +reg_class g3_regL(R_G3H,R_G3); reg_class o2_regL(R_O2H,R_O2); reg_class o7_regL(R_O7H,R_O7); @@ -1743,7 +1744,7 @@ const bool Matcher::convL2FSupported(void) { // // NOTE: If the platform does not provide any short branch variants, then // this method should return false for offset 0. -bool Matcher::is_short_branch_offset(int offset) { +bool Matcher::is_short_branch_offset(int rule, int offset) { return false; } @@ -1926,18 +1927,23 @@ encode %{ $mem$$base, $mem$$disp, $mem$$index, $dst$$reg); %} + enc_class simple_form3_mem_reg( memory mem, iRegI dst ) %{ + emit_form3_mem_reg(cbuf, this, $primary, -1, + $mem$$base, $mem$$disp, $mem$$index, $dst$$reg); + %} + enc_class form3_mem_reg_little( memory mem, iRegI dst) %{ - emit_form3_mem_reg_asi(cbuf, this, $primary, $tertiary, + emit_form3_mem_reg_asi(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, $mem$$index, $dst$$reg, Assembler::ASI_PRIMARY_LITTLE); %} enc_class form3_mem_prefetch_read( memory mem ) %{ - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, $mem$$index, 0/*prefetch function many-reads*/); %} enc_class form3_mem_prefetch_write( memory mem ) %{ - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, $mem$$index, 2/*prefetch function many-writes*/); %} @@ -1945,8 +1951,8 @@ encode %{ assert( Assembler::is_simm13($mem$$disp ), "need disp and disp+4" ); assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" ); guarantee($mem$$index == R_G0_enc, "double index?"); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc ); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg ); emit3_simm13( cbuf, Assembler::arith_op, $reg$$reg, Assembler::sllx_op3, $reg$$reg, 0x1020 ); emit3( cbuf, Assembler::arith_op, $reg$$reg, Assembler::or_op3, $reg$$reg, 0, R_O7_enc ); %} @@ -1956,14 +1962,14 @@ encode %{ assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" ); guarantee($mem$$index == R_G0_enc, "double index?"); // Load long with 2 instructions - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 ); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp+4, R_G0_enc, $reg$$reg+1 ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 ); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, $reg$$reg+1 ); %} //%%% form3_mem_plus_4_reg is a hack--get rid of it enc_class form3_mem_plus_4_reg( memory mem, iRegI dst ) %{ guarantee($mem$$disp, "cannot offset a reg-reg operand by 4"); - emit_form3_mem_reg(cbuf, this, $primary, $tertiary, $mem$$base, $mem$$disp + 4, $mem$$index, $dst$$reg); + emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp + 4, $mem$$index, $dst$$reg); %} enc_class form3_g0_rs2_rd_move( iRegI rs2, iRegI rd ) %{ @@ -2683,7 +2689,7 @@ enc_class Fast_Lock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ assert(Rbox != Rscratch, ""); assert(Rbox != Rmark, ""); - __ compiler_lock_object(Roop, Rmark, Rbox, Rscratch, _counters); + __ compiler_lock_object(Roop, Rmark, Rbox, Rscratch, _counters, UseBiasedLocking && !UseOptoBiasInlining); %} enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ @@ -2699,7 +2705,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ assert(Rbox != Rscratch, ""); assert(Rbox != Rmark, ""); - __ compiler_unlock_object(Roop, Rmark, Rbox, Rscratch); + __ compiler_unlock_object(Roop, Rmark, Rbox, Rscratch, UseBiasedLocking && !UseOptoBiasInlining); %} enc_class enc_cas( iRegP mem, iRegP old, iRegP new ) %{ @@ -2711,8 +2717,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ // casx_under_lock picks 1 of 3 encodings: // For 32-bit pointers you get a 32-bit CAS // For 64-bit pointers you get a 64-bit CASX - __ casx_under_lock(Rmem, Rold, Rnew, // Swap(*Rmem,Rnew) if *Rmem == Rold - (address) StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + __ casn(Rmem, Rold, Rnew); // Swap(*Rmem,Rnew) if *Rmem == Rold __ cmp( Rold, Rnew ); %} @@ -3761,6 +3766,14 @@ operand g1RegL() %{ interface(REG_INTER); %} +operand g3RegL() %{ + constraint(ALLOC_IN_RC(g3_regL)); + match(iRegL); + + format %{ %} + interface(REG_INTER); +%} + // Int Register safe // This is 64bit safe operand iRegIsafe() %{ @@ -5062,7 +5075,7 @@ instruct stkI_to_regF(regF dst, stackSlotI src) %{ size(4); format %{ "LDF $src,$dst\t! stkI to regF" %} opcode(Assembler::ldf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadF_stk); %} @@ -5073,7 +5086,7 @@ instruct stkL_to_regD(regD dst, stackSlotL src) %{ size(4); format %{ "LDDF $src,$dst\t! stkL to regD" %} opcode(Assembler::lddf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadD_stk); %} @@ -5084,7 +5097,7 @@ instruct regF_to_stkI(stackSlotI dst, regF src) %{ size(4); format %{ "STF $src,$dst\t! regF to stkI" %} opcode(Assembler::stf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreF_stk_reg); %} @@ -5095,7 +5108,7 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{ size(4); format %{ "STDF $src,$dst\t! regD to stkL" %} opcode(Assembler::stdf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreD_stk_reg); %} @@ -5106,7 +5119,7 @@ instruct regI_to_stkLHi(stackSlotL dst, iRegI src) %{ format %{ "STW $src,$dst.hi\t! long\n\t" "STW R_G0,$dst.lo" %} opcode(Assembler::stw_op3); - ins_encode(form3_mem_reg(dst, src), form3_mem_plus_4_reg(dst, R_G0)); + ins_encode(simple_form3_mem_reg(dst, src), form3_mem_plus_4_reg(dst, R_G0)); ins_pipe(lstoreI_stk_reg); %} @@ -5117,7 +5130,7 @@ instruct regL_to_stkD(stackSlotD dst, iRegL src) %{ size(4); format %{ "STX $src,$dst\t! regL to stkD" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_stk_reg); %} @@ -5131,7 +5144,7 @@ instruct stkI_to_regI( iRegI dst, stackSlotI src ) %{ size(4); format %{ "LDUW $src,$dst\t!stk" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5143,7 +5156,7 @@ instruct regI_to_stkI( stackSlotI dst, iRegI src ) %{ size(4); format %{ "STW $src,$dst\t!stk" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} @@ -5155,7 +5168,7 @@ instruct stkL_to_regL( iRegL dst, stackSlotL src ) %{ size(4); format %{ "LDX $src,$dst\t! long" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5167,7 +5180,7 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ size(4); format %{ "STX $src,$dst\t! long" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} @@ -5179,7 +5192,7 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ size(4); format %{ "LDX $src,$dst\t!ptr" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5190,7 +5203,7 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ size(4); format %{ "STX $src,$dst\t!ptr" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} #else // _LP64 @@ -5200,7 +5213,7 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ ins_cost(MEMORY_REF_COST); format %{ "LDUW $src,$dst\t!ptr" %} opcode(Assembler::lduw_op3, Assembler::ldst_op); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -5210,7 +5223,7 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ ins_cost(MEMORY_REF_COST); format %{ "STW $src,$dst\t!ptr" %} opcode(Assembler::stw_op3, Assembler::ldst_op); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} #endif // _LP64 @@ -5273,7 +5286,7 @@ instruct loadB(iRegI dst, memory mem) %{ size(4); format %{ "LDSB $mem,$dst" %} opcode(Assembler::ldsb_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5285,7 +5298,7 @@ instruct loadUB(iRegI dst, memory mem, immI_255 bytemask) %{ size(4); format %{ "LDUB $mem,$dst" %} opcode(Assembler::ldub_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5297,7 +5310,7 @@ instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{ size(4); format %{ "LDUB $mem,$dst" %} opcode(Assembler::ldub_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5309,7 +5322,7 @@ instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{ size(4); format %{ "LDUH $mem,$dst" %} opcode(Assembler::lduh_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5321,7 +5334,7 @@ instruct loadC(iRegI dst, memory mem) %{ size(4); format %{ "LDUH $mem,$dst" %} opcode(Assembler::lduh_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5333,7 +5346,7 @@ instruct loadI(iRegI dst, memory mem) %{ format %{ "LDUW $mem,$dst" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -5344,7 +5357,7 @@ instruct loadL(iRegL dst, memory mem ) %{ size(4); format %{ "LDX $mem,$dst\t! long" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -5359,7 +5372,7 @@ instruct loadL_unaligned(iRegL dst, memory mem, o7RegI tmp) %{ "\tSLLX #32, $dst, $dst\n" "\tOR $dst, R_O7, $dst" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg_long_unaligned_marshal( mem, dst )); + ins_encode(form3_mem_reg_long_unaligned_marshal( mem, dst )); ins_pipe(iload_mem); %} @@ -5370,7 +5383,7 @@ instruct loadA8B(regD dst, memory mem) %{ size(4); format %{ "LDDF $mem,$dst\t! packed8B" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5381,7 +5394,7 @@ instruct loadA4C(regD dst, memory mem) %{ size(4); format %{ "LDDF $mem,$dst\t! packed4C" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5392,7 +5405,7 @@ instruct loadA4S(regD dst, memory mem) %{ size(4); format %{ "LDDF $mem,$dst\t! packed4S" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5403,7 +5416,7 @@ instruct loadA2I(regD dst, memory mem) %{ size(4); format %{ "LDDF $mem,$dst\t! packed2I" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5415,7 +5428,7 @@ instruct loadRange(iRegI dst, memory mem) %{ size(4); format %{ "LDUW $mem,$dst\t! range" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -5427,7 +5440,7 @@ instruct loadI_freg(regF dst, memory mem) %{ format %{ "LDF $mem,$dst\t! for fitos/fitod" %} opcode(Assembler::ldf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadF_mem); %} @@ -5514,7 +5527,7 @@ instruct loadS(iRegI dst, memory mem) %{ size(4); format %{ "LDSH $mem,$dst" %} opcode(Assembler::ldsh_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mask_mem); %} @@ -5526,7 +5539,7 @@ instruct loadD(regD dst, memory mem) %{ size(4); format %{ "LDDF $mem,$dst" %} opcode(Assembler::lddf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadD_mem); %} @@ -5550,7 +5563,7 @@ instruct loadF(regF dst, memory mem) %{ size(4); format %{ "LDF $mem,$dst" %} opcode(Assembler::ldf_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(floadF_mem); %} @@ -5719,7 +5732,7 @@ instruct storeB(memory mem, iRegI src) %{ size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5730,7 +5743,7 @@ instruct storeB0(memory mem, immI0 src) %{ size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5741,7 +5754,7 @@ instruct storeCM0(memory mem, immI0 src) %{ size(4); format %{ "STB $src,$mem\t! CMS card-mark byte 0" %} opcode(Assembler::stb_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5753,7 +5766,7 @@ instruct storeC(memory mem, iRegI src) %{ size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5764,7 +5777,7 @@ instruct storeC0(memory mem, immI0 src) %{ size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5776,7 +5789,7 @@ instruct storeI(memory mem, iRegI src) %{ size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5787,7 +5800,7 @@ instruct storeL(memory mem, iRegL src) %{ size(4); format %{ "STX $src,$mem\t! long" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(istore_mem_reg); %} @@ -5798,7 +5811,7 @@ instruct storeI0(memory mem, immI0 src) %{ size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5809,7 +5822,7 @@ instruct storeL0(memory mem, immL0 src) %{ size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -5821,7 +5834,7 @@ instruct storeI_Freg(memory mem, regF src) %{ size(4); format %{ "STF $src,$mem\t! after fstoi/fdtoi" %} opcode(Assembler::stf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreF_mem_reg); %} @@ -5904,7 +5917,7 @@ instruct storeD( memory mem, regD src) %{ size(4); format %{ "STDF $src,$mem" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -5915,7 +5928,7 @@ instruct storeD0( memory mem, immD0 src) %{ size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -5927,7 +5940,7 @@ instruct storeF( memory mem, regF src) %{ size(4); format %{ "STF $src,$mem" %} opcode(Assembler::stf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreF_mem_reg); %} @@ -5938,7 +5951,7 @@ instruct storeF0( memory mem, immF0 src) %{ size(4); format %{ "STW $src,$mem\t! storeF0" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreF_mem_zero); %} @@ -5949,7 +5962,7 @@ instruct storeA8B(memory mem, regD src) %{ size(4); format %{ "STDF $src,$mem\t! packed8B" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -6004,7 +6017,7 @@ instruct storeA8B0(memory mem, immI0 zero) %{ size(4); format %{ "STX $zero,$mem\t! packed8B" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -6015,7 +6028,7 @@ instruct storeA4C(memory mem, regD src) %{ size(4); format %{ "STDF $src,$mem\t! packed4C" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -6026,7 +6039,7 @@ instruct storeA4C0(memory mem, immI0 zero) %{ size(4); format %{ "STX $zero,$mem\t! packed4C" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -6037,7 +6050,7 @@ instruct storeA2I(memory mem, regD src) %{ size(4); format %{ "STDF $src,$mem\t! packed2I" %} opcode(Assembler::stdf_op3); - ins_encode( form3_mem_reg( mem, src ) ); + ins_encode(simple_form3_mem_reg( mem, src ) ); ins_pipe(fstoreD_mem_reg); %} @@ -6048,7 +6061,7 @@ instruct storeA2I0(memory mem, immI0 zero) %{ size(4); format %{ "STX $zero,$mem\t! packed2I" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( mem, R_G0 ) ); + ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); ins_pipe(fstoreD_mem_zero); %} @@ -6162,7 +6175,7 @@ instruct stfSSD(stackSlotD stkSlot, regD src) %{ ins_cost(MEMORY_REF_COST); format %{ "STDF $src,$stkSlot\t!stk" %} opcode(Assembler::stdf_op3); - ins_encode(form3_mem_reg(stkSlot, src)); + ins_encode(simple_form3_mem_reg(stkSlot, src)); ins_pipe(fstoreD_stk_reg); %} @@ -6172,7 +6185,7 @@ instruct ldfSSD(regD dst, stackSlotD stkSlot) %{ ins_cost(MEMORY_REF_COST); format %{ "LDDF $stkSlot,$dst\t!stk" %} opcode(Assembler::lddf_op3); - ins_encode(form3_mem_reg(stkSlot, dst)); + ins_encode(simple_form3_mem_reg(stkSlot, dst)); ins_pipe(floadD_stk); %} @@ -6182,7 +6195,7 @@ instruct stfSSF(stackSlotF stkSlot, regF src) %{ ins_cost(MEMORY_REF_COST); format %{ "STF $src,$stkSlot\t!stk" %} opcode(Assembler::stf_op3); - ins_encode(form3_mem_reg(stkSlot, src)); + ins_encode(simple_form3_mem_reg(stkSlot, src)); ins_pipe(fstoreF_stk_reg); %} @@ -6584,7 +6597,7 @@ instruct loadLLocked(iRegL dst, memory mem) %{ size(4); format %{ "LDX $mem,$dst\t! long" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( mem, dst ) ); + ins_encode(simple_form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -6597,32 +6610,23 @@ instruct storePConditional( iRegP heap_top_ptr, iRegP oldval, g3RegP newval, fla ins_pipe( long_memory_op ); %} -instruct storeLConditional_bool(iRegP mem_ptr, iRegL oldval, iRegL newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{ - match(Set res (StoreLConditional mem_ptr (Binary oldval newval))); - effect( USE mem_ptr, KILL ccr, KILL tmp1); - // Marshal the register pairs into V9 64-bit registers, then do the compare-and-swap - format %{ - "MOV $newval,R_O7\n\t" - "CASXA [$mem_ptr],$oldval,R_O7\t! If $oldval==[$mem_ptr] Then store R_O7 into [$mem_ptr], set R_O7=[$mem_ptr] in any case\n\t" - "CMP $oldval,R_O7\t\t! See if we made progress\n\t" - "MOV 1,$res\n\t" - "MOVne xcc,R_G0,$res" - %} - ins_encode( enc_casx(mem_ptr, oldval, newval), - enc_lflags_ne_to_boolean(res) ); +// Conditional-store of an int value. +instruct storeIConditional( iRegP mem_ptr, iRegI oldval, g3RegI newval, flagsReg icc ) %{ + match(Set icc (StoreIConditional mem_ptr (Binary oldval newval))); + effect( KILL newval ); + format %{ "CASA [$mem_ptr],$oldval,$newval\t! If $oldval==[$mem_ptr] Then store $newval into [$mem_ptr], set $newval=[$mem_ptr] in any case\n\t" + "CMP $oldval,$newval\t\t! See if we made progress" %} + ins_encode( enc_cas(mem_ptr,oldval,newval) ); ins_pipe( long_memory_op ); %} -instruct storeLConditional_flags(iRegP mem_ptr, iRegL oldval, iRegL newval, flagsRegL xcc, o7RegI tmp1, immI0 zero) %{ - match(Set xcc (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero)); - effect( USE mem_ptr, KILL tmp1); - // Marshal the register pairs into V9 64-bit registers, then do the compare-and-swap - format %{ - "MOV $newval,R_O7\n\t" - "CASXA [$mem_ptr],$oldval,R_O7\t! If $oldval==[$mem_ptr] Then store R_O7 into [$mem_ptr], set R_O7=[$mem_ptr] in any case\n\t" - "CMP $oldval,R_O7\t\t! See if we made progress" - %} - ins_encode( enc_casx(mem_ptr, oldval, newval)); +// Conditional-store of a long value. +instruct storeLConditional( iRegP mem_ptr, iRegL oldval, g3RegL newval, flagsRegL xcc ) %{ + match(Set xcc (StoreLConditional mem_ptr (Binary oldval newval))); + effect( KILL newval ); + format %{ "CASXA [$mem_ptr],$oldval,$newval\t! If $oldval==[$mem_ptr] Then store $newval into [$mem_ptr], set $newval=[$mem_ptr] in any case\n\t" + "CMP $oldval,$newval\t\t! See if we made progress" %} + ins_encode( enc_cas(mem_ptr,oldval,newval) ); ins_pipe( long_memory_op ); %} @@ -7405,6 +7409,34 @@ instruct orL_reg_imm13(iRegL dst, iRegL src1, immL13 con) %{ ins_pipe(ialu_reg_imm); %} +#ifndef _LP64 + +// Use sp_ptr_RegP to match G2 (TLS register) without spilling. +instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ + match(Set dst (OrI src1 (CastP2X src2))); + + size(4); + format %{ "OR $src1,$src2,$dst" %} + opcode(Assembler::or_op3, Assembler::arith_op); + ins_encode( form3_rs1_rs2_rd( src1, src2, dst ) ); + ins_pipe(ialu_reg_reg); +%} + +#else + +instruct orL_reg_castP2X(iRegL dst, iRegL src1, sp_ptr_RegP src2) %{ + match(Set dst (OrL src1 (CastP2X src2))); + + ins_cost(DEFAULT_COST); + size(4); + format %{ "OR $src1,$src2,$dst\t! long" %} + opcode(Assembler::or_op3, Assembler::arith_op); + ins_encode( form3_rs1_rs2_rd( src1, src2, dst ) ); + ins_pipe(ialu_reg_reg); +%} + +#endif + // Xor Instructions // Register Xor instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ @@ -7666,7 +7698,7 @@ instruct convI2D_mem( regD_low dst, memory mem ) %{ format %{ "LDF $mem,$dst\n\t" "FITOD $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitod_opf); - ins_encode( form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); + ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); ins_pipe(floadF_mem); %} @@ -7696,7 +7728,7 @@ instruct convI2F_mem( regF dst, memory mem ) %{ format %{ "LDF $mem,$dst\n\t" "FITOS $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitos_opf); - ins_encode( form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); + ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); ins_pipe(floadF_mem); %} @@ -7738,7 +7770,7 @@ instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{ size(4); format %{ "LDUW $src,$dst\t! MoveF2I" %} opcode(Assembler::lduw_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -7750,7 +7782,7 @@ instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{ size(4); format %{ "LDF $src,$dst\t! MoveI2F" %} opcode(Assembler::ldf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadF_stk); %} @@ -7762,7 +7794,7 @@ instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{ size(4); format %{ "LDX $src,$dst\t! MoveD2L" %} opcode(Assembler::ldx_op3); - ins_encode( form3_mem_reg( src, dst ) ); + ins_encode(simple_form3_mem_reg( src, dst ) ); ins_pipe(iload_mem); %} @@ -7774,7 +7806,7 @@ instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{ size(4); format %{ "LDDF $src,$dst\t! MoveL2D" %} opcode(Assembler::lddf_op3); - ins_encode(form3_mem_reg(src, dst)); + ins_encode(simple_form3_mem_reg(src, dst)); ins_pipe(floadD_stk); %} @@ -7786,7 +7818,7 @@ instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{ size(4); format %{ "STF $src,$dst\t!MoveF2I" %} opcode(Assembler::stf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreF_stk_reg); %} @@ -7798,7 +7830,7 @@ instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{ size(4); format %{ "STW $src,$dst\t!MoveI2F" %} opcode(Assembler::stw_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} @@ -7810,7 +7842,7 @@ instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{ size(4); format %{ "STDF $src,$dst\t!MoveD2L" %} opcode(Assembler::stdf_op3); - ins_encode(form3_mem_reg(dst, src)); + ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreD_stk_reg); %} @@ -7822,7 +7854,7 @@ instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{ size(4); format %{ "STX $src,$dst\t!MoveL2D" %} opcode(Assembler::stx_op3); - ins_encode( form3_mem_reg( dst, src ) ); + ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index a16d332ba6b..9b4981dff7a 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -956,7 +956,7 @@ class StubGenerator: public StubCodeGenerator { // Load a little early; will load 1 off the end of the array. // Ok for now; revisit if we have other uses of this routine. if (UseCompressedOops) { - __ ld(L1_ary_ptr,0,L2_super);// Will load a little early + __ lduw(L1_ary_ptr,0,L2_super);// Will load a little early } else { __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early } @@ -973,7 +973,7 @@ class StubGenerator: public StubCodeGenerator { #ifdef _LP64 __ subcc(L2_super,L4_ooptmp,Rret); // Check for match; zero in Rret for a hit __ br( Assembler::notEqual, false, Assembler::pt, loop ); - __ delayed()->ld(L1_ary_ptr,0,L2_super);// Will load a little early + __ delayed()->lduw(L1_ary_ptr,0,L2_super);// Will load a little early #else ShouldNotReachHere(); #endif diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index ec208540ad0..edf0d3dbcaf 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -621,6 +621,10 @@ address Assembler::locate_operand(address inst, WhichOperand which) { debug_only(has_disp32 = true); break; + case 0xF0: // Lock + assert(os::is_MP(), "only on MP"); + goto again_after_prefix; + case 0xF3: // For SSE case 0xF2: // For SSE2 switch (0xFF & *ip++) { diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index c2b64771803..32cb356a1a1 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1780,7 +1780,8 @@ class MacroAssembler: public Assembler { // check info (currently consumed only by C1). If // swap_reg_contains_mark is true then returns -1 as it is assumed // the calling code has already passed any potential faults. - int biased_locking_enter(Register lock_reg, Register obj_reg, Register swap_reg, Register tmp_reg, + int biased_locking_enter(Register lock_reg, Register obj_reg, + Register swap_reg, Register tmp_reg, bool swap_reg_contains_mark, Label& done, Label* slow_case = NULL, BiasedLockingCounters* counters = NULL); diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 589051e06bf..5f6f8724adb 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -495,8 +495,8 @@ void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) { void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { Compile* C = ra_->C; if( C->in_24_bit_fp_mode() ) { - tty->print("FLDCW 24 bit fpu control word"); - tty->print_cr(""); tty->print("\t"); + st->print("FLDCW 24 bit fpu control word"); + st->print_cr(""); st->print("\t"); } int framesize = C->frame_slots() << LogBytesPerInt; @@ -510,22 +510,22 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { // stack. But the stack safety zone should account for that. // See bugs 4446381, 4468289, 4497237. if (C->need_stack_bang(framesize)) { - tty->print_cr("# stack bang"); tty->print("\t"); + st->print_cr("# stack bang"); st->print("\t"); } - tty->print_cr("PUSHL EBP"); tty->print("\t"); + st->print_cr("PUSHL EBP"); st->print("\t"); if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth - tty->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); - tty->print_cr(""); tty->print("\t"); + st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); + st->print_cr(""); st->print("\t"); framesize -= wordSize; } if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { if (framesize) { - tty->print("SUB ESP,%d\t# Create frame",framesize); + st->print("SUB ESP,%d\t# Create frame",framesize); } } else { - tty->print("SUB ESP,%d\t# Create frame",framesize); + st->print("SUB ESP,%d\t# Create frame",framesize); } } #endif @@ -725,18 +725,19 @@ static enum RC rc_class( OptoReg::Name reg ) { return rc_xmm; } -static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size ) { +static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, + int opcode, const char *op_str, int size, outputStream* st ) { if( cbuf ) { emit_opcode (*cbuf, opcode ); encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( opcode == 0x8B || opcode == 0x89 ) { // MOV - if( is_load ) tty->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); - else tty->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); + if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); + else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); } else { // FLD, FST, PUSH, POP - tty->print("%s [ESP + #%d]",op_str,offset); + st->print("%s [ESP + #%d]",op_str,offset); } #endif } @@ -746,7 +747,7 @@ static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset // Helper for XMM registers. Extra opcode bits, limited syntax. static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, - int offset, int reg_lo, int reg_hi, int size ) { + int offset, int reg_lo, int reg_hi, int size, outputStream* st ) { if( cbuf ) { if( reg_lo+1 == reg_hi ) { // double move? if( is_load && !UseXmmLoadAndClearUpper ) @@ -764,17 +765,17 @@ static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( reg_lo+1 == reg_hi ) { // double move? - if( is_load ) tty->print("%s %s,[ESP + #%d]", + if( is_load ) st->print("%s %s,[ESP + #%d]", UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", Matcher::regName[reg_lo], offset); - else tty->print("MOVSD [ESP + #%d],%s", + else st->print("MOVSD [ESP + #%d],%s", offset, Matcher::regName[reg_lo]); } else { - if( is_load ) tty->print("MOVSS %s,[ESP + #%d]", + if( is_load ) st->print("MOVSS %s,[ESP + #%d]", Matcher::regName[reg_lo], offset); - else tty->print("MOVSS [ESP + #%d],%s", + else st->print("MOVSS [ESP + #%d],%s", offset, Matcher::regName[reg_lo]); } #endif @@ -785,7 +786,7 @@ static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, - int src_hi, int dst_hi, int size ) { + int src_hi, int dst_hi, int size, outputStream* st ) { if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers if( cbuf ) { if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { @@ -796,11 +797,11 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? - tty->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } else { - tty->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } #endif } @@ -813,11 +814,11 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); + if( size != 0 ) st->print("\n\t"); if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? - tty->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } else { - tty->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); + st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); } #endif } @@ -825,28 +826,29 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst } } -static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size ) { +static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) { if( cbuf ) { emit_opcode(*cbuf, 0x8B ); emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); - tty->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); + if( size != 0 ) st->print("\n\t"); + st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); #endif } return size+2; } -static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, int offset, int size ) { +static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, + int offset, int size, outputStream* st ) { if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there if( cbuf ) { emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it) emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] ); #ifndef PRODUCT } else if( !do_size ) { - if( size != 0 ) tty->print("\n\t"); - tty->print("FLD %s",Matcher::regName[src_lo]); + if( size != 0 ) st->print("\n\t"); + st->print("FLD %s",Matcher::regName[src_lo]); #endif } size += 2; @@ -864,7 +866,7 @@ static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int assert( !OptoReg::is_valid(src_hi) && !OptoReg::is_valid(dst_hi), "no non-adjacent float-stores" ); } - return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size); + return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size, st); } uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { @@ -892,16 +894,16 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { if( src_second == dst_first ) { // overlapping stack copy ranges assert( src_second_rc == rc_stack && dst_second_rc == rc_stack, "we only expect a stk-stk copy here" ); - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits } // move low bits - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size); - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size, st); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size, st); if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { // mov second bits - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); } return size; } @@ -909,15 +911,15 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo // -------------------------------------- // Check for integer reg-reg copy if( src_first_rc == rc_int && dst_first_rc == rc_int ) - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size); + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size, st); // Check for integer store if( src_first_rc == rc_int && dst_first_rc == rc_stack ) - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size); + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size, st); // Check for integer load if( dst_first_rc == rc_int && src_first_rc == rc_stack ) - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size); + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size, st); // -------------------------------------- // Check for float reg-reg copy @@ -951,7 +953,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo // Check for float store if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { - return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size); + return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size, st); } // Check for float load @@ -987,17 +989,17 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || (src_first+1 == src_second && dst_first+1 == dst_second), "no non-adjacent float-moves" ); - return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size); + return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size, st); } // Check for xmm store if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { - return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size); + return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size, st); } // Check for float xmm load if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) { - return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size); + return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size, st); } // Copy from float reg to xmm reg @@ -1017,10 +1019,10 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo } size += 4; - size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size); + size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size, st); // Copy from the temp memory to the xmm reg. - size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size); + size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size, st); if( cbuf ) { emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8] @@ -1047,15 +1049,15 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo // Check for second word int-int move if( src_second_rc == rc_int && dst_second_rc == rc_int ) - return impl_mov_helper(cbuf,do_size,src_second,dst_second,size); + return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st); // Check for second word integer store if( src_second_rc == rc_int && dst_second_rc == rc_stack ) - return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size); + return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st); // Check for second word integer load if( dst_second_rc == rc_int && src_second_rc == rc_stack ) - return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size); + return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st); Unimplemented(); @@ -1318,7 +1320,11 @@ const uint Matcher::vector_ideal_reg(void) { // // NOTE: If the platform does not provide any short branch variants, then // this method should return false for offset 0. -bool Matcher::is_short_branch_offset(int offset) { +bool Matcher::is_short_branch_offset(int rule, int offset) { + // the short version of jmpConUCF2 contains multiple branches, + // making the reach slightly less + if (rule == jmpConUCF2_rule) + return (-126 <= offset && offset <= 125); return (-128 <= offset && offset <= 127); } @@ -3307,7 +3313,7 @@ encode %{ // Beware -- there's a subtle invariant that fetch of the markword // at [FETCH], below, will never observe a biased encoding (*101b). // If this invariant is not held we risk exclusion (safety) failure. - if (UseBiasedLocking) { + if (UseBiasedLocking && !UseOptoBiasInlining) { masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); } @@ -3528,7 +3534,7 @@ encode %{ // Critically, the biased locking test must have precedence over // and appear before the (box->dhw == 0) recursive stack-lock test. - if (UseBiasedLocking) { + if (UseBiasedLocking && !UseOptoBiasInlining) { masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); } @@ -5272,6 +5278,15 @@ operand eFlagsRegU() %{ interface(REG_INTER); %} +operand eFlagsRegUCF() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + predicate(false); + + format %{ "EFLAGS_U_CF" %} + interface(REG_INTER); +%} + // Condition Code Register used by long compare operand flagsReg_long_LTGE() %{ constraint(ALLOC_IN_RC(int_flags)); @@ -5749,12 +5764,12 @@ operand cmpOp() %{ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0xC); - greater_equal(0xD); - less_equal(0xE); - greater(0xF); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0xC, "l"); + greater_equal(0xD, "ge"); + less_equal(0xE, "le"); + greater(0xF, "g"); %} %} @@ -5766,12 +5781,47 @@ operand cmpOpU() %{ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0x2); - greater_equal(0x3); - less_equal(0x6); - greater(0x7); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + +// Floating comparisons that don't require any fixup for the unordered case +operand cmpOpUCF() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::lt || + n->as_Bool()->_test._test == BoolTest::ge || + n->as_Bool()->_test._test == BoolTest::le || + n->as_Bool()->_test._test == BoolTest::gt); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + + +// Floating comparisons that can be fixed up with extra conditional jumps +operand cmpOpUCF2() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::eq); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); %} %} @@ -5796,12 +5846,12 @@ operand cmpOp_commute() %{ format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0xF); - greater_equal(0xE); - less_equal(0xD); - greater(0xC); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0xF, "g"); + greater_equal(0xE, "le"); + less_equal(0xD, "ge"); + greater(0xC, "l"); %} %} @@ -7357,7 +7407,7 @@ instruct cmovI_reg(eRegI dst, eRegI src, eFlagsReg cr, cmpOp cop ) %{ ins_pipe( pipe_cmov_reg ); %} -instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{ +instruct cmovI_regU( cmpOpU cop, eFlagsRegU cr, eRegI dst, eRegI src ) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); ins_cost(200); @@ -7367,6 +7417,15 @@ instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{ ins_pipe( pipe_cmov_reg ); %} +instruct cmovI_regUCF( cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, eRegI src ) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovI_regU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ predicate(VM_Version::supports_cmov() ); @@ -7379,7 +7438,7 @@ instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ %} // Conditional move -instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ +instruct cmovI_memU(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); ins_cost(250); @@ -7389,6 +7448,15 @@ instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ ins_pipe( pipe_cmov_mem ); %} +instruct cmovI_memUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, memory src) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); + ins_cost(250); + expand %{ + cmovI_memU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ predicate(VM_Version::supports_cmov() ); @@ -7416,7 +7484,7 @@ instruct cmovP_reg_nonP6(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ %} // Conditional move -instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{ +instruct cmovP_regU(cmpOpU cop, eFlagsRegU cr, eRegP dst, eRegP src ) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); ins_cost(200); @@ -7426,6 +7494,15 @@ instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{ ins_pipe( pipe_cmov_reg ); %} +instruct cmovP_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegP dst, eRegP src ) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovP_regU(cop, cr, dst, src); + %} +%} + // DISABLED: Requires the ADLC to emit a bottom_type call that // correctly meets the two pointer arguments; one is an incoming // register but the other is a memory operand. ALSO appears to @@ -7555,6 +7632,15 @@ instruct fcmovX_regU(cmpOpU cop, eFlagsRegU cr, regX dst, regX src) %{ ins_pipe( pipe_slow ); %} +instruct fcmovX_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regX dst, regX src) %{ + predicate (UseSSE>=1); + match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + fcmovX_regU(cop, cr, dst, src); + %} +%} + // unsigned version instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ predicate (UseSSE>=2); @@ -7573,6 +7659,15 @@ instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ ins_pipe( pipe_slow ); %} +instruct fcmovXD_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regXD dst, regXD src) %{ + predicate (UseSSE>=2); + match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + fcmovXD_regU(cop, cr, dst, src); + %} +%} + instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{ predicate(VM_Version::supports_cmov() ); match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); @@ -7595,6 +7690,15 @@ instruct cmovL_regU(cmpOpU cop, eFlagsRegU cr, eRegL dst, eRegL src) %{ ins_pipe( pipe_cmov_reg_long ); %} +instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{ + predicate(VM_Version::supports_cmov() ); + match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovL_regU(cop, cr, dst, src); + %} +%} + //----------Arithmetic Instructions-------------------------------------------- //----------Addition Instructions---------------------------------------------- // Integer Addition Instructions @@ -7826,33 +7930,36 @@ instruct storePConditional( memory heap_top_ptr, eAXRegP oldval, eRegP newval, e ins_pipe( pipe_cmpxchg ); %} -// Conditional-store of a long value -// Returns a boolean value (0/1) on success. Implemented with a CMPXCHG8 on Intel. -// mem_ptr can actually be in either ESI or EDI -instruct storeLConditional( eRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{ - match(Set res (StoreLConditional mem_ptr (Binary oldval newval))); - effect(KILL cr); - // EDX:EAX is killed if there is contention, but then it's also unused. - // In the common case of no contention, EDX:EAX holds the new oop address. - format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" - "MOV $res,0\n\t" - "JNE,s fail\n\t" - "MOV $res,1\n" - "fail:" %} - ins_encode( enc_cmpxchg8(mem_ptr), - enc_flags_ne_to_boolean(res) ); +// Conditional-store of an int value. +// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG on Intel. +instruct storeIConditional( memory mem, eAXRegI oldval, eRegI newval, eFlagsReg cr ) %{ + match(Set cr (StoreIConditional mem (Binary oldval newval))); + effect(KILL oldval); + format %{ "CMPXCHG $mem,$newval\t# If EAX==$mem Then store $newval into $mem" %} + ins_encode( lock_prefix, Opcode(0x0F), Opcode(0xB1), RegMem(newval, mem) ); ins_pipe( pipe_cmpxchg ); %} -// Conditional-store of a long value -// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG8 on Intel. -// mem_ptr can actually be in either ESI or EDI -instruct storeLConditional_flags( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr, immI0 zero ) %{ - match(Set cr (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero)); - // EDX:EAX is killed if there is contention, but then it's also unused. - // In the common case of no contention, EDX:EAX holds the new oop address. - format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %} - ins_encode( enc_cmpxchg8(mem_ptr) ); +// Conditional-store of a long value. +// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG8 on Intel. +instruct storeLConditional( memory mem, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{ + match(Set cr (StoreLConditional mem (Binary oldval newval))); + effect(KILL oldval); + format %{ "XCHG EBX,ECX\t# correct order for CMPXCHG8 instruction\n\t" + "CMPXCHG8 $mem,ECX:EBX\t# If EDX:EAX==$mem Then store ECX:EBX into $mem\n\t" + "XCHG EBX,ECX" + %} + ins_encode %{ + // Note: we need to swap rbx, and rcx before and after the + // cmpxchg8 instruction because the instruction uses + // rcx as the high order word of the new value to store but + // our register encoding uses rbx. + __ xchgl(as_Register(EBX_enc), as_Register(ECX_enc)); + if( os::is_MP() ) + __ lock(); + __ cmpxchg8(Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp)); + __ xchgl(as_Register(EBX_enc), as_Register(ECX_enc)); + %} ins_pipe( pipe_cmpxchg ); %} @@ -8319,6 +8426,7 @@ instruct shrI_eReg_imm(eRegI dst, immI8 shift, eFlagsReg cr) %{ ins_pipe( ialu_reg ); %} + // Logical Shift Right by 24, followed by Arithmetic Shift Left by 24. // This idiom is used by the compiler for the i2b bytecode. instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour, eFlagsReg cr) %{ @@ -8436,6 +8544,18 @@ instruct orI_eReg(eRegI dst, eRegI src, eFlagsReg cr) %{ ins_pipe( ialu_reg_reg ); %} +instruct orI_eReg_castP2X(eRegI dst, eRegP src, eFlagsReg cr) %{ + match(Set dst (OrI dst (CastP2X src))); + effect(KILL cr); + + size(2); + format %{ "OR $dst,$src" %} + opcode(0x0B); + ins_encode( OpcP, RegReg( dst, src) ); + ins_pipe( ialu_reg_reg ); +%} + + // Or Register with Immediate instruct orI_eReg_imm(eRegI dst, immI src, eFlagsReg cr) %{ match(Set dst (OrI dst src)); @@ -9200,6 +9320,18 @@ instruct cmpD_cc_P6(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ ins_pipe( pipe_slow ); %} +instruct cmpD_cc_P6CF(eFlagsRegUCF cr, regD src1, regD src2) %{ + predicate(VM_Version::supports_cmov() && UseSSE <=1); + match(Set cr (CmpD src1 src2)); + ins_cost(150); + format %{ "FLD $src1\n\t" + "FUCOMIP ST,$src2 // P6 instruction" %} + opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ + ins_encode( Push_Reg_D(src1), + OpcP, RegOpc(src2)); + ins_pipe( pipe_slow ); +%} + // Compare & branch instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ predicate(UseSSE<=1); @@ -9264,6 +9396,16 @@ instruct cmpXD_cc(eFlagsRegU cr, regXD dst, regXD src, eAXRegI rax) %{ ins_pipe( pipe_slow ); %} +instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD dst, regXD src) %{ + predicate(UseSSE>=2); + match(Set cr (CmpD dst src)); + ins_cost(100); + format %{ "COMISD $dst,$src" %} + opcode(0x66, 0x0F, 0x2F); + ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); + ins_pipe( pipe_slow ); +%} + // float compare and set condition codes in EFLAGS by XMM regs instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ predicate(UseSSE>=2); @@ -9280,6 +9422,16 @@ instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ ins_pipe( pipe_slow ); %} +instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD dst, memory src) %{ + predicate(UseSSE>=2); + match(Set cr (CmpD dst (LoadD src))); + ins_cost(100); + format %{ "COMISD $dst,$src" %} + opcode(0x66, 0x0F, 0x2F); + ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src)); + ins_pipe( pipe_slow ); +%} + // Compare into -1,0,1 in XMM instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ predicate(UseSSE>=2); @@ -10167,6 +10319,18 @@ instruct cmpF_cc_P6(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ ins_pipe( pipe_slow ); %} +instruct cmpF_cc_P6CF(eFlagsRegUCF cr, regF src1, regF src2) %{ + predicate(VM_Version::supports_cmov() && UseSSE == 0); + match(Set cr (CmpF src1 src2)); + ins_cost(100); + format %{ "FLD $src1\n\t" + "FUCOMIP ST,$src2 // P6 instruction" %} + opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ + ins_encode( Push_Reg_D(src1), + OpcP, RegOpc(src2)); + ins_pipe( pipe_slow ); +%} + // Compare & branch instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ @@ -10232,6 +10396,16 @@ instruct cmpX_cc(eFlagsRegU cr, regX dst, regX src, eAXRegI rax) %{ ins_pipe( pipe_slow ); %} +instruct cmpX_ccCF(eFlagsRegUCF cr, regX dst, regX src) %{ + predicate(UseSSE>=1); + match(Set cr (CmpF dst src)); + ins_cost(100); + format %{ "COMISS $dst,$src" %} + opcode(0x0F, 0x2F); + ins_encode(OpcP, OpcS, RegReg(dst, src)); + ins_pipe( pipe_slow ); +%} + // float compare and set condition codes in EFLAGS by XMM regs instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ predicate(UseSSE>=1); @@ -10248,6 +10422,16 @@ instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ ins_pipe( pipe_slow ); %} +instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX dst, memory src) %{ + predicate(UseSSE>=1); + match(Set cr (CmpF dst (LoadF src))); + ins_cost(100); + format %{ "COMISS $dst,$src" %} + opcode(0x0F, 0x2F); + ins_encode(OpcP, OpcS, RegMem(dst, src)); + ins_pipe( pipe_slow ); +%} + // Compare into -1,0,1 in XMM instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ predicate(UseSSE>=1); @@ -12099,6 +12283,19 @@ instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ ins_pc_relative(1); %} +instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "J$cop,u $labl\t# Loop end" %} + size(6); + opcode(0x0F, 0x80); + ins_encode( Jcc( cop, labl) ); + ins_pipe( pipe_jcc ); + ins_pc_relative(1); +%} + // Jump Direct Conditional - using unsigned comparison instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ match(If cop cmp); @@ -12108,8 +12305,63 @@ instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ format %{ "J$cop,u $labl" %} size(6); opcode(0x0F, 0x80); - ins_encode( Jcc( cop, labl) ); - ins_pipe( pipe_jcc ); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + +instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "J$cop,u $labl" %} + size(6); + opcode(0x0F, 0x80); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + +instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"JP,u $labl\n\t" + $$emit$$"J$cop,u $labl" + } else { + $$emit$$"JP,u done\n\t" + $$emit$$"J$cop,u $labl\n\t" + $$emit$$"done:" + } + %} + size(12); + opcode(0x0F, 0x80); + ins_encode %{ + Label* l = $labl$$label; + $$$emit8$primary; + emit_cc(cbuf, $secondary, Assembler::parity); + int parity_disp = -1; + bool ok = false; + if ($cop$$cmpcode == Assembler::notEqual) { + // the two jumps 6 bytes apart so the jump distances are too + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 6; + ok = true; + } else { + ShouldNotReachHere(); + } + emit_d32(cbuf, parity_disp); + $$$emit8$primary; + emit_cc(cbuf, $secondary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + emit_d32(cbuf, disp); + %} + ins_pipe(pipe_jcc); ins_pc_relative(1); %} @@ -12208,7 +12460,7 @@ instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{ effect(USE labl); ins_cost(300); - format %{ "J$cop,s $labl" %} + format %{ "J$cop,s $labl\t# Loop end" %} size(2); opcode(0x70); ins_encode( JccShort( cop, labl) ); @@ -12223,7 +12475,21 @@ instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ effect(USE labl); ins_cost(300); - format %{ "J$cop,us $labl" %} + format %{ "J$cop,us $labl\t# Loop end" %} + size(2); + opcode(0x70); + ins_encode( JccShort( cop, labl) ); + ins_pipe( pipe_jcc ); + ins_pc_relative(1); + ins_short_branch(1); +%} + +instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ "J$cop,us $labl\t# Loop end" %} size(2); opcode(0x70); ins_encode( JccShort( cop, labl) ); @@ -12247,6 +12513,60 @@ instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ ins_short_branch(1); %} +instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ "J$cop,us $labl" %} + size(2); + opcode(0x70); + ins_encode( JccShort( cop, labl) ); + ins_pipe( pipe_jcc ); + ins_pc_relative(1); + ins_short_branch(1); +%} + +instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"JP,u,s $labl\n\t" + $$emit$$"J$cop,u,s $labl" + } else { + $$emit$$"JP,u,s done\n\t" + $$emit$$"J$cop,u,s $labl\n\t" + $$emit$$"done:" + } + %} + size(4); + opcode(0x70); + ins_encode %{ + Label* l = $labl$$label; + emit_cc(cbuf, $primary, Assembler::parity); + int parity_disp = -1; + if ($cop$$cmpcode == Assembler::notEqual) { + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 2; + } else { + ShouldNotReachHere(); + } + emit_d8(cbuf, parity_disp); + emit_cc(cbuf, $primary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + emit_d8(cbuf, disp); + assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); + assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); + %} + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + // ============================================================================ // Long Compare // diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 4245284593d..9b5621f3903 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -2004,9 +2004,12 @@ const uint Matcher::vector_ideal_reg(void) { // // NOTE: If the platform does not provide any short branch variants, then // this method should return false for offset 0. -bool Matcher::is_short_branch_offset(int offset) -{ - return -0x80 <= offset && offset < 0x80; +bool Matcher::is_short_branch_offset(int rule, int offset) { + // the short version of jmpConUCF2 contains multiple branches, + // making the reach slightly less + if (rule == jmpConUCF2_rule) + return (-126 <= offset && offset <= 125); + return (-128 <= offset && offset <= 127); } const bool Matcher::isSimpleConstant64(jlong value) { @@ -3569,7 +3572,7 @@ encode %{ // at [FETCH], below, will never observe a biased encoding (*101b). // If this invariant is not held we'll suffer exclusion (safety) failure. - if (UseBiasedLocking) { + if (UseBiasedLocking && !UseOptoBiasInlining) { masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters); masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH] } @@ -3657,7 +3660,7 @@ encode %{ } else { Label DONE_LABEL, Stacked, CheckSucc ; - if (UseBiasedLocking) { + if (UseBiasedLocking && !UseOptoBiasInlining) { masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); } @@ -5134,6 +5137,15 @@ operand rFlagsRegU() interface(REG_INTER); %} +operand rFlagsRegUCF() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + predicate(false); + + format %{ "RFLAGS_U_CF" %} + interface(REG_INTER); +%} + // Float register operands operand regF() %{ @@ -5405,12 +5417,12 @@ operand cmpOp() format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0xC); - greater_equal(0xD); - less_equal(0xE); - greater(0xF); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0xC, "l"); + greater_equal(0xD, "ge"); + less_equal(0xE, "le"); + greater(0xF, "g"); %} %} @@ -5423,12 +5435,48 @@ operand cmpOpU() format %{ "" %} interface(COND_INTER) %{ - equal(0x4); - not_equal(0x5); - less(0x2); - greater_equal(0x3); - less_equal(0x6); - greater(0x7); + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + + +// Floating comparisons that don't require any fixup for the unordered case +operand cmpOpUCF() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::lt || + n->as_Bool()->_test._test == BoolTest::ge || + n->as_Bool()->_test._test == BoolTest::le || + n->as_Bool()->_test._test == BoolTest::gt); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); + %} +%} + + +// Floating comparisons that can be fixed up with extra conditional jumps +operand cmpOpUCF2() %{ + match(Bool); + predicate(n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::eq); + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x2, "b"); + greater_equal(0x3, "nb"); + less_equal(0x6, "be"); + greater(0x7, "nbe"); %} %} @@ -7176,8 +7224,7 @@ instruct cmovI_reg(rRegI dst, rRegI src, rFlagsReg cr, cmpOp cop) ins_pipe(pipe_cmov_reg); %} -instruct cmovI_regU(rRegI dst, rRegI src, rFlagsRegU cr, cmpOpU cop) -%{ +instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{ match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); ins_cost(200); // XXX @@ -7187,9 +7234,16 @@ instruct cmovI_regU(rRegI dst, rRegI src, rFlagsRegU cr, cmpOpU cop) ins_pipe(pipe_cmov_reg); %} +instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{ + match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovI_regU(cop, cr, dst, src); + %} +%} + // Conditional move -instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) -%{ +instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{ match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); ins_cost(250); // XXX @@ -7211,6 +7265,14 @@ instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src) ins_pipe(pipe_cmov_mem); %} +instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{ + match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); + ins_cost(250); + expand %{ + cmovI_memU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop) %{ @@ -7224,7 +7286,7 @@ instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop) %} // Conditional move -instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop) +instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src) %{ match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); @@ -7235,6 +7297,14 @@ instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop) ins_pipe(pipe_cmov_reg); %} +instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{ + match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovN_regU(cop, cr, dst, src); + %} +%} + // Conditional move instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) %{ @@ -7248,7 +7318,7 @@ instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) %} // Conditional move -instruct cmovP_regU(rRegP dst, rRegP src, rFlagsRegU cr, cmpOpU cop) +instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src) %{ match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); @@ -7259,6 +7329,14 @@ instruct cmovP_regU(rRegP dst, rRegP src, rFlagsRegU cr, cmpOpU cop) ins_pipe(pipe_cmov_reg); // XXX %} +instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{ + match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovP_regU(cop, cr, dst, src); + %} +%} + // DISABLED: Requires the ADLC to emit a bottom_type call that // correctly meets the two pointer arguments; one is an incoming // register but the other is a memory operand. ALSO appears to @@ -7319,6 +7397,14 @@ instruct cmovL_regU(cmpOpU cop, rFlagsRegU cr, rRegL dst, rRegL src) ins_pipe(pipe_cmov_reg); // XXX %} +instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{ + match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovL_regU(cop, cr, dst, src); + %} +%} + instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src) %{ match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); @@ -7330,6 +7416,14 @@ instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src) ins_pipe(pipe_cmov_mem); // XXX %} +instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{ + match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src)))); + ins_cost(200); + expand %{ + cmovL_memU(cop, cr, dst, src); + %} +%} + instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src) %{ match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); @@ -7366,6 +7460,14 @@ instruct cmovF_regU(cmpOpU cop, rFlagsRegU cr, regF dst, regF src) ins_pipe(pipe_slow); %} +instruct cmovF_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regF dst, regF src) %{ + match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovF_regU(cop, cr, dst, src); + %} +%} + instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src) %{ match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); @@ -7390,6 +7492,14 @@ instruct cmovD_regU(cmpOpU cop, rFlagsRegU cr, regD dst, regD src) ins_pipe(pipe_slow); %} +instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{ + match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); + ins_cost(200); + expand %{ + cmovD_regU(cop, cr, dst, src); + %} +%} + //----------Arithmetic Instructions-------------------------------------------- //----------Addition Instructions---------------------------------------------- @@ -7735,7 +7845,7 @@ instruct storePConditional(memory heap_top_ptr, rFlagsReg cr) %{ match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval))); - + format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) " "If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %} opcode(0x0F, 0xB1); @@ -7746,53 +7856,40 @@ instruct storePConditional(memory heap_top_ptr, ins_pipe(pipe_cmpxchg); %} -// Conditional-store of a long value -// Returns a boolean value (0/1) on success. Implemented with a -// CMPXCHG8 on Intel. mem_ptr can actually be in either RSI or RDI - -instruct storeLConditional(rRegI res, - memory mem_ptr, - rax_RegL oldval, rRegL newval, - rFlagsReg cr) +// Conditional-store of an int value. +// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG. +instruct storeIConditional(memory mem, rax_RegI oldval, rRegI newval, rFlagsReg cr) %{ - match(Set res (StoreLConditional mem_ptr (Binary oldval newval))); - effect(KILL cr); + match(Set cr (StoreIConditional mem (Binary oldval newval))); + effect(KILL oldval); - format %{ "cmpxchgq $mem_ptr, $newval\t# (long) " - "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" - "sete $res\n\t" - "movzbl $res, $res" %} + format %{ "cmpxchgl $mem, $newval\t# If rax == $mem then store $newval into $mem" %} opcode(0x0F, 0xB1); ins_encode(lock_prefix, - REX_reg_mem_wide(newval, mem_ptr), + REX_reg_mem(newval, mem), OpcP, OpcS, - reg_mem(newval, mem_ptr), - REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete - REX_reg_breg(res, res), // movzbl - Opcode(0xF), Opcode(0xB6), reg_reg(res, res)); + reg_mem(newval, mem)); ins_pipe(pipe_cmpxchg); %} -// Conditional-store of a long value -// ZF flag is set on success, reset otherwise. Implemented with a -// CMPXCHG8 on Intel. mem_ptr can actually be in either RSI or RDI -instruct storeLConditional_flags(memory mem_ptr, - rax_RegL oldval, rRegL newval, - rFlagsReg cr, - immI0 zero) +// Conditional-store of a long value. +// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG. +instruct storeLConditional(memory mem, rax_RegL oldval, rRegL newval, rFlagsReg cr) %{ - match(Set cr (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero)); + match(Set cr (StoreLConditional mem (Binary oldval newval))); + effect(KILL oldval); - format %{ "cmpxchgq $mem_ptr, $newval\t# (long) " - "If rax == $mem_ptr then store $newval into $mem_ptr" %} + format %{ "cmpxchgq $mem, $newval\t# If rax == $mem then store $newval into $mem" %} opcode(0x0F, 0xB1); ins_encode(lock_prefix, - REX_reg_mem_wide(newval, mem_ptr), + REX_reg_mem_wide(newval, mem), OpcP, OpcS, - reg_mem(newval, mem_ptr)); + reg_mem(newval, mem)); ins_pipe(pipe_cmpxchg); %} + +// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them instruct compareAndSwapP(rRegI res, memory mem_ptr, rax_RegP oldval, rRegP newval, @@ -7816,7 +7913,6 @@ instruct compareAndSwapP(rRegI res, ins_pipe( pipe_cmpxchg ); %} -// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them instruct compareAndSwapL(rRegI res, memory mem_ptr, rax_RegL oldval, rRegL newval, @@ -8766,6 +8862,7 @@ instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr) ins_pipe(ialu_reg); %} + // Logical Shift Right by 8-bit immediate instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr) %{ @@ -9475,6 +9572,18 @@ instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr) ins_pipe(ialu_reg_reg); %} +// Use any_RegP to match R15 (TLS register) without spilling. +instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{ + match(Set dst (OrL dst (CastP2X src))); + effect(KILL cr); + + format %{ "orq $dst, $src\t# long" %} + opcode(0x0B); + ins_encode(REX_reg_reg_wide(dst, src), OpcP, reg_reg(dst, src)); + ins_pipe(ialu_reg_reg); +%} + + // Or Register with Immediate instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr) %{ @@ -9716,6 +9825,17 @@ instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2) ins_pipe(pipe_slow); %} +instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{ + match(Set cr (CmpF src1 src2)); + + ins_cost(145); + format %{ "ucomiss $src1, $src2" %} + ins_encode %{ + __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + instruct cmpF_cc_mem(rFlagsRegU cr, regF src1, memory src2) %{ match(Set cr (CmpF src1 (LoadF src2))); @@ -9733,6 +9853,16 @@ instruct cmpF_cc_mem(rFlagsRegU cr, regF src1, memory src2) ins_pipe(pipe_slow); %} +instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{ + match(Set cr (CmpF src1 (LoadF src2))); + + ins_cost(100); + format %{ "ucomiss $src1, $src2" %} + opcode(0x0F, 0x2E); + ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2)); + ins_pipe(pipe_slow); +%} + instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2) %{ match(Set cr (CmpF src1 src2)); @@ -9750,6 +9880,16 @@ instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2) ins_pipe(pipe_slow); %} +instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{ + match(Set cr (CmpF src1 src2)); + + ins_cost(100); + format %{ "ucomiss $src1, $src2" %} + opcode(0x0F, 0x2E); + ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2)); + ins_pipe(pipe_slow); +%} + instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2) %{ match(Set cr (CmpD src1 src2)); @@ -9767,6 +9907,17 @@ instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2) ins_pipe(pipe_slow); %} +instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{ + match(Set cr (CmpD src1 src2)); + + ins_cost(100); + format %{ "ucomisd $src1, $src2 test" %} + ins_encode %{ + __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + instruct cmpD_cc_mem(rFlagsRegU cr, regD src1, memory src2) %{ match(Set cr (CmpD src1 (LoadD src2))); @@ -9784,6 +9935,16 @@ instruct cmpD_cc_mem(rFlagsRegU cr, regD src1, memory src2) ins_pipe(pipe_slow); %} +instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{ + match(Set cr (CmpD src1 (LoadD src2))); + + ins_cost(100); + format %{ "ucomisd $src1, $src2" %} + opcode(0x66, 0x0F, 0x2E); + ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2)); + ins_pipe(pipe_slow); +%} + instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2) %{ match(Set cr (CmpD src1 src2)); @@ -9801,6 +9962,16 @@ instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2) ins_pipe(pipe_slow); %} +instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{ + match(Set cr (CmpD src1 src2)); + + ins_cost(100); + format %{ "ucomisd $src1, [$src2]" %} + opcode(0x66, 0x0F, 0x2E); + ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2)); + ins_pipe(pipe_slow); +%} + // Compare into -1,0,1 instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr) %{ @@ -11406,8 +11577,7 @@ instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl) %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{ match(CountedLoopEnd cop cmp); effect(USE labl); @@ -11420,14 +11590,26 @@ instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) ins_pc_relative(1); %} +instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "j$cop,u $labl\t# loop end" %} + size(6); + opcode(0x0F, 0x80); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + // Jump Direct Conditional - using unsigned comparison -instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{ match(If cop cmp); effect(USE labl); ins_cost(300); - format %{ "j$cop,u $labl" %} + format %{ "j$cop,u $labl" %} size(6); opcode(0x0F, 0x80); ins_encode(Jcc(cop, labl)); @@ -11435,6 +11617,59 @@ instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) ins_pc_relative(1); %} +instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ "j$cop,u $labl" %} + size(6); + opcode(0x0F, 0x80); + ins_encode(Jcc(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + +instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(200); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"jp,u $labl\n\t" + $$emit$$"j$cop,u $labl" + } else { + $$emit$$"jp,u done\n\t" + $$emit$$"j$cop,u $labl\n\t" + $$emit$$"done:" + } + %} + size(12); + opcode(0x0F, 0x80); + ins_encode %{ + Label* l = $labl$$label; + $$$emit8$primary; + emit_cc(cbuf, $secondary, Assembler::parity); + int parity_disp = -1; + if ($cop$$cmpcode == Assembler::notEqual) { + // the two jumps 6 bytes apart so the jump distances are too + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 6; + } else { + ShouldNotReachHere(); + } + emit_d32(cbuf, parity_disp); + $$$emit8$primary; + emit_cc(cbuf, $secondary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; + emit_d32(cbuf, disp); + %} + ins_pipe(pipe_jcc); + ins_pc_relative(1); +%} + // ============================================================================ // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary // superklass array for an instance of the superklass. Set a hidden @@ -11505,8 +11740,7 @@ instruct partialSubtypeCheck_vs_Zero(rFlagsReg cr, // specific code section of the file. // Jump Direct - Label defines a relative address from JMP+1 -instruct jmpDir_short(label labl) -%{ +instruct jmpDir_short(label labl) %{ match(Goto); effect(USE labl); @@ -11521,8 +11755,7 @@ instruct jmpDir_short(label labl) %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) -%{ +instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{ match(If cop cr); effect(USE labl); @@ -11537,13 +11770,12 @@ instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) -%{ +instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{ match(CountedLoopEnd cop cr); effect(USE labl); ins_cost(300); - format %{ "j$cop,s $labl" %} + format %{ "j$cop,s $labl\t# loop end" %} size(2); opcode(0x70); ins_encode(JccShort(cop, labl)); @@ -11553,11 +11785,39 @@ instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %} // Jump Direct Conditional - Label defines a relative address from Jcc+1 -instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{ match(CountedLoopEnd cop cmp); effect(USE labl); + ins_cost(300); + format %{ "j$cop,us $labl\t# loop end" %} + size(2); + opcode(0x70); + ins_encode(JccShort(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + +instruct jmpLoopEndUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ + match(CountedLoopEnd cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ "j$cop,us $labl\t# loop end" %} + size(2); + opcode(0x70); + ins_encode(JccShort(cop, labl)); + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + +// Jump Direct Conditional - using unsigned comparison +instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + ins_cost(300); format %{ "j$cop,us $labl" %} size(2); @@ -11568,9 +11828,7 @@ instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) ins_short_branch(1); %} -// Jump Direct Conditional - using unsigned comparison -instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) -%{ +instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{ match(If cop cmp); effect(USE labl); @@ -11584,6 +11842,46 @@ instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) ins_short_branch(1); %} +instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ + match(If cop cmp); + effect(USE labl); + + ins_cost(300); + format %{ $$template + if ($cop$$cmpcode == Assembler::notEqual) { + $$emit$$"jp,u,s $labl\n\t" + $$emit$$"j$cop,u,s $labl" + } else { + $$emit$$"jp,u,s done\n\t" + $$emit$$"j$cop,u,s $labl\n\t" + $$emit$$"done:" + } + %} + size(4); + opcode(0x70); + ins_encode %{ + Label* l = $labl$$label; + emit_cc(cbuf, $primary, Assembler::parity); + int parity_disp = -1; + if ($cop$$cmpcode == Assembler::notEqual) { + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + } else if ($cop$$cmpcode == Assembler::equal) { + parity_disp = 2; + } else { + ShouldNotReachHere(); + } + emit_d8(cbuf, parity_disp); + emit_cc(cbuf, $primary, $cop$$cmpcode); + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; + emit_d8(cbuf, disp); + assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); + assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); + %} + ins_pipe(pipe_jcc); + ins_pc_relative(1); + ins_short_branch(1); +%} + // ============================================================================ // inlined locking and unlocking diff --git a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.ad b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.ad index ec4725a1cbc..ed92526efe4 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.ad +++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.ad @@ -103,16 +103,16 @@ encode %{ // This name is KNOWN by the ADLC and cannot be changed. // The ADLC forces a 'TypeRawPtr::BOTTOM' output type // for this guy. -instruct tlsLoadP(eAXRegP dst, eFlagsReg cr) %{ +instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ match(Set dst (ThreadLocal)); effect(DEF dst, KILL cr); - format %{ "MOV EAX, Thread::current()" %} + format %{ "MOV $dst, Thread::current()" %} ins_encode( linux_tlsencode(dst) ); ins_pipe( ialu_reg_fat ); %} -instruct TLS(eAXRegP dst) %{ +instruct TLS(eRegP dst) %{ match(Set dst (ThreadLocal)); expand %{ diff --git a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad index 911a8ad7d13..3f1110606ea 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad @@ -110,16 +110,16 @@ encode %{ // This name is KNOWN by the ADLC and cannot be changed. // The ADLC forces a 'TypeRawPtr::BOTTOM' output type // for this guy. -instruct tlsLoadP(eAXRegP dst, eFlagsReg cr) %{ +instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ match(Set dst (ThreadLocal)); effect(DEF dst, KILL cr); - format %{ "MOV EAX, Thread::current()" %} + format %{ "MOV $dst, Thread::current()" %} ins_encode( solaris_tlsencode(dst) ); ins_pipe( ialu_reg_fat ); %} -instruct TLS(eAXRegP dst) %{ +instruct TLS(eRegP dst) %{ match(Set dst (ThreadLocal)); expand %{ diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java index 6fbbe90e912..d5b2a2ecdc0 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java @@ -28,6 +28,7 @@ import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.services.InputGraphProvider; import java.awt.BorderLayout; import java.io.Serializable; +import javax.swing.SwingUtilities; import org.openide.ErrorManager; import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerUtils; @@ -151,14 +152,18 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan } public void resultChanged(LookupEvent lookupEvent) { - InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class); + final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class); if (p != null) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { InputGraph graph = p.getGraph(); if (graph != null) { Group g = graph.getGroup(); rootNode.update(graph, g.getMethod()); } } + }); + } } final static class ResolvableHelper implements Serializable { diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java index 8b794b11aa5..e497b349f6c 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java @@ -33,7 +33,7 @@ import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; import java.util.HashSet; -import java.util.Hashtable; +import java.util.HashMap; import java.util.Set; import javax.swing.BorderFactory; import org.netbeans.api.visual.action.ActionFactory; @@ -44,7 +44,6 @@ import org.netbeans.api.visual.action.SelectProvider; import org.netbeans.api.visual.action.WidgetAction; import org.netbeans.api.visual.anchor.AnchorFactory; import org.netbeans.api.visual.anchor.AnchorShape; -import com.sun.hotspot.igv.controlflow.HierarchicalGraphLayout; import org.netbeans.api.visual.layout.LayoutFactory; import org.netbeans.api.visual.router.RouterFactory; import org.netbeans.api.visual.widget.LayerWidget; @@ -61,8 +60,8 @@ import org.openide.util.Lookup; */ public class ControlFlowScene extends GraphScene implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider { - private Set selection; - private Hashtable blockMap; + private HashSet selection; + private HashMap blockMap; private InputGraph oldGraph; private LayerWidget edgeLayer; private LayerWidget mainLayer; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java index 968cdd531b7..8cb6405f669 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java @@ -28,6 +28,7 @@ import com.sun.hotspot.igv.data.services.InputGraphProvider; import java.awt.BorderLayout; import java.io.Serializable; import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; import org.openide.ErrorManager; import org.openide.util.Lookup; import org.openide.util.LookupEvent; @@ -143,13 +144,17 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen public void resultChanged(LookupEvent lookupEvent) { - InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class); + final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class); if (p != null) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { InputGraph g = p.getGraph(); if (g != null) { scene.setGraph(g); } } + }); + } } @Override diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java index b5398edaeea..2805d749df8 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java @@ -24,6 +24,7 @@ package com.sun.hotspot.igv.coordinator; import com.sun.hotspot.igv.coordinator.actions.RemoveCookie; +import com.sun.hotspot.igv.data.ChangedListener; import com.sun.hotspot.igv.data.Group; import com.sun.hotspot.igv.data.services.GroupOrganizer; import com.sun.hotspot.igv.data.InputGraph; @@ -50,17 +51,24 @@ public class FolderNode extends AbstractNode { private List subFolders; private FolderChildren children; - private static class FolderChildren extends Children.Keys { + private static class FolderChildren extends Children.Keys implements ChangedListener { private FolderNode parent; + private List registeredGroups; public void setParent(FolderNode parent) { this.parent = parent; + this.registeredGroups = new ArrayList(); } @Override protected Node[] createNodes(Object arg0) { + for(Group g : registeredGroups) { + g.getChangedEvent().removeListener(this); + } + registeredGroups.clear(); + Pair> p = (Pair>) arg0; if (p.getLeft().length() == 0) { @@ -69,6 +77,8 @@ public class FolderNode extends AbstractNode { for (InputGraph graph : g.getGraphs()) { curNodes.add(new GraphNode(graph)); } + g.getChangedEvent().addListener(this); + registeredGroups.add(g); } Node[] result = new Node[curNodes.size()]; @@ -85,7 +95,13 @@ public class FolderNode extends AbstractNode { @Override public void addNotify() { this.setKeys(parent.structure); + } + public void changed(Group source) { + List>> newStructure = new ArrayList>>(); + for(Pair> p : parent.structure) { + refreshKey(p); + } } } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java index 27d09c38f71..53f90f24255 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java @@ -31,7 +31,7 @@ import java.util.List; * * @author Thomas Wuerthinger */ -public class GraphDocument extends Properties.Object implements ChangedEventProvider { +public class GraphDocument extends Properties.Entity implements ChangedEventProvider { private List groups; private ChangedEvent changedEvent; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java index 8f0aa15e992..a54cd19bc0b 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java @@ -37,7 +37,7 @@ import java.util.Set; * * @author Thomas Wuerthinger */ -public class Group extends Properties.Object implements ChangedEventProvider { +public class Group extends Properties.Entity implements ChangedEventProvider { private List graphs; private transient ChangedEvent changedEvent; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java index b929fd627c6..9e18344234e 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java @@ -23,26 +23,25 @@ */ package com.sun.hotspot.igv.data; -import com.sun.hotspot.igv.data.Properties; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Hashtable; +import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; /** * * @author Thomas Wuerthinger */ -public class InputGraph extends Properties.Object { +public class InputGraph extends Properties.Entity { - private Map nodes; - private Set edges; + private HashMap nodes; + private ArrayList edges; private Group parent; - private Map blocks; - private Map nodeToBlock; + private HashMap blocks; + private HashMap nodeToBlock; private boolean isDifferenceGraph; public InputGraph(Group parent) { @@ -61,10 +60,10 @@ public class InputGraph extends Properties.Object { public InputGraph(Group parent, InputGraph last, String name) { this.parent = parent; setName(name); - nodes = new Hashtable(); - edges = new HashSet(); - blocks = new Hashtable(); - nodeToBlock = new Hashtable(); + nodes = new HashMap(); + edges = new ArrayList(); + blocks = new HashMap(); + nodeToBlock = new HashMap(); if (last != null) { for (InputNode n : last.getNodes()) { @@ -182,8 +181,8 @@ public class InputGraph extends Properties.Object { return nodes.remove(index); } - public Set getEdges() { - return Collections.unmodifiableSet(edges); + public Collection getEdges() { + return Collections.unmodifiableList(edges); } public void removeEdge(InputEdge c) { diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java index eac6b1a0308..586efdc975c 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java @@ -32,7 +32,7 @@ import java.util.List; * * @author Thomas Wuerthinger */ -public class InputMethod extends Properties.Object { +public class InputMethod extends Properties.Entity { private String name; private int bci; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java index ad15d141ac9..27dd3a52abb 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java @@ -27,7 +27,7 @@ package com.sun.hotspot.igv.data; * * @author Thomas Wuerthinger */ -public class InputNode extends Properties.Object { +public class InputNode extends Properties.Entity { private int id; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java index 07a29962f9f..75c62611d4b 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java @@ -26,24 +26,22 @@ package com.sun.hotspot.igv.data; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; +import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; + /** * * @author Thomas Wuerthinger */ -public class Properties implements Serializable { +public class Properties implements Serializable, Iterable { public static final long serialVersionUID = 1L; - private Map map; + private String[] map = new String[4]; public Properties() { - map = new HashMap(5); } @Override @@ -54,10 +52,7 @@ public class Properties implements Serializable { Properties p = (Properties) o; - if (getProperties().size() != p.getProperties().size()) { - return false; - } - for (Property prop : getProperties()) { + for (Property prop : this) { String value = p.get(prop.getName()); if (value == null || !value.equals(prop.getValue())) { return false; @@ -75,32 +70,33 @@ public class Properties implements Serializable { public Properties(String name, String value) { this(); - this.add(new Property(name, value)); + this.setProperty(name, value); } public Properties(String name, String value, String name1, String value1) { this(name, value); - this.add(new Property(name1, value1)); + this.setProperty(name1, value1); } public Properties(String name, String value, String name1, String value1, String name2, String value2) { this(name, value, name1, value1); - this.add(new Property(name2, value2)); + this.setProperty(name2, value2); } public Properties(Properties p) { - map = new HashMap(p.map); + map = new String[p.map.length]; + System.arraycopy(map, 0, p.map, 0, p.map.length); } - public static class Object implements Provider { + public static class Entity implements Provider { private Properties properties; - public Object() { + public Entity() { properties = new Properties(); } - public Object(Properties.Object object) { + public Entity(Properties.Entity object) { properties = new Properties(object.getProperties()); } @@ -109,6 +105,14 @@ public class Properties implements Serializable { } } + private String getProperty(String key) { + for (int i = 0; i < map.length; i += 2) + if (map[i] != null && map[i].equals(key)) { + return map[i + 1]; + } + return null; + } + public interface PropertyMatcher { String getName(); @@ -173,13 +177,15 @@ public class Properties implements Serializable { } public Property selectSingle(PropertyMatcher matcher) { - - Property p = this.map.get(matcher.getName()); - if (p == null) { - return null; + String value = null; + for (int i = 0; i < map.length; i += 2) { + if (map[i] != null && matcher.getName().equals(map[i])) { + value = map[i + 1]; + break; + } } - if (matcher.match(p.getValue())) { - return p; + if (value != null && matcher.match(value)) { + return new Property(matcher.getName(), value); } else { return null; } @@ -194,8 +200,11 @@ public class Properties implements Serializable { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); - for (Property p : map.values()) { - sb.append(p.toString()); + for (int i = 0; i < map.length; i += 2) { + if (map[i + 1] != null) { + String p = map[i + 1]; + sb.append(map[i] + " = " + map[i + 1] + "; "); + } } return sb.append("]").toString(); } @@ -241,41 +250,51 @@ public class Properties implements Serializable { } public String get(String key) { - Property p = map.get(key); - if (p == null) { - return null; - } else { - return p.getValue(); - } - } - - public String getProperty(String string) { - return get(string); - } - - public Property setProperty(String name, String value) { - - if (value == null) { - // remove this property - return map.remove(name); - } else { - Property p = map.get(name); - if (p == null) { - p = new Property(name, value); - map.put(name, p); - } else { - p.setValue(value); + for (int i = 0; i < map.length; i += 2) { + if (map[i] != null && map[i].equals(key)) { + return map[i + 1]; } - return p; } + return null; } - public Collection getProperties() { - return Collections.unmodifiableCollection(map.values()); + public void setProperty(String name, String value) { + for (int i = 0; i < map.length; i += 2) { + if (map[i] != null && map[i].equals(name)) { + String p = map[i + 1]; + if (value == null) { + // remove this property + map[i] = null; + map[i + 1] = null; + } else { + map[i + 1] = value; + } + return; + } + } + if (value == null) { + return; + } + for (int i = 0; i < map.length; i += 2) { + if (map[i] == null) { + map[i] = name; + map[i + 1] = value; + return; + } + } + String[] newMap = new String[map.length + 4]; + System.arraycopy(map, 0, newMap, 0, map.length); + newMap[map.length] = name; + newMap[map.length + 1] = value; + map = newMap; + } + + public Iterator getProperties() { + return iterator(); } public void add(Properties properties) { - for (Property p : properties.getProperties()) { + for (Property p : properties) { add(p); } } @@ -283,6 +302,35 @@ public class Properties implements Serializable { public void add(Property property) { assert property.getName() != null; assert property.getValue() != null; - map.put(property.getName(), property); + setProperty(property.getName(), property.getValue()); + } + class PropertiesIterator implements Iterator, Iterable { + public Iterator iterator() { + return this; + } + + int index; + + public boolean hasNext() { + while (index < map.length && map[index + 1] == null) + index += 2; + return index < map.length; + } + + public Property next() { + if (index < map.length) { + index += 2; + return new Property(map[index - 2], map[index - 1]); + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException("Not supported yet."); + } + + } + public Iterator iterator() { + return new PropertiesIterator(); } } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java index 6694153d3b7..d18990805c2 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java @@ -32,18 +32,19 @@ import java.io.Serializable; public class Property implements Serializable { public static final long serialVersionUID = 1L; + private String name; private String value; - public Property() { + private Property() { this(null, null); } - public Property(Property p) { + private Property(Property p) { this(p.getName(), p.getValue()); } - public Property(String name) { + private Property(String name) { this(name, null); } @@ -60,16 +61,19 @@ public class Property implements Serializable { return value; } - public void setName(String s) { - this.name = s; - } - - public void setValue(String s) { - this.value = s; - } - @Override public String toString() { return name + " = " + value + "; "; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Property)) return false; + Property p2 = (Property)o; + return name.equals(p2.name) && value.equals(p2.value); + } + @Override + public int hashCode() { + return name.hashCode() + value == null ? 0 : value.hashCode(); + } } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java index 410ee7c41a8..3d3c9e60892 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java @@ -38,6 +38,7 @@ import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler; import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor; import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler; import java.io.IOException; +import java.util.HashMap; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; @@ -88,6 +89,18 @@ public class Parser { private TopElementHandler xmlDocument = new TopElementHandler(); private boolean difference; private GroupCallback groupCallback; + private HashMap idCache = new HashMap(); + private int maxId = 0; + + private int lookupID(String i) { + Integer id = idCache.get(i); + if (id == null) { + id = maxId++; + idCache.put(i, id); + } + return id.intValue(); + } + // private ElementHandler topHandler = new ElementHandler(TOP_ELEMENT) { @@ -187,13 +200,13 @@ public class Parser { previous = null; } InputGraph curGraph = new InputGraph(getParentObject(), previous, name); - getParentObject().addGraph(curGraph); this.graph = curGraph; return curGraph; } @Override protected void end(String text) throws SAXException { + getParentObject().addGraph(graph); graph.resolveBlockLinks(); } }; @@ -207,7 +220,7 @@ public class Parser { @Override protected InputBlock start() throws SAXException { InputGraph graph = getParentObject(); - String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); + String name = readRequiredAttribute(BLOCK_NAME_PROPERTY).intern(); InputBlock b = new InputBlock(getParentObject(), name); graph.addBlock(b); return b; @@ -224,7 +237,7 @@ public class Parser { int id = 0; try { - id = Integer.parseInt(s); + id = lookupID(s); } catch (NumberFormatException e) { throw new SAXException(e); } @@ -252,7 +265,7 @@ public class Parser { String s = readRequiredAttribute(NODE_ID_PROPERTY); int id = 0; try { - id = Integer.parseInt(s); + id = lookupID(s); } catch (NumberFormatException e) { throw new SAXException(e); } @@ -269,7 +282,7 @@ public class Parser { String s = readRequiredAttribute(NODE_ID_PROPERTY); int id = 0; try { - id = Integer.parseInt(s); + id = lookupID(s); } catch (NumberFormatException e) { throw new SAXException(e); } @@ -280,7 +293,7 @@ public class Parser { private HandoverElementHandler edgesHandler = new HandoverElementHandler(EDGES_ELEMENT); // Local class for edge elements - private static class EdgeElementHandler extends ElementHandler { + private class EdgeElementHandler extends ElementHandler { public EdgeElementHandler(String name) { super(name); @@ -298,8 +311,8 @@ public class Parser { toIndex = Integer.parseInt(toIndexString); } - from = Integer.parseInt(readRequiredAttribute(FROM_PROPERTY)); - to = Integer.parseInt(readRequiredAttribute(TO_PROPERTY)); + from = lookupID(readRequiredAttribute(FROM_PROPERTY)); + to = lookupID(readRequiredAttribute(TO_PROPERTY)); } catch (NumberFormatException e) { throw new SAXException(e); } @@ -344,18 +357,16 @@ public class Parser { } }; // - private ElementHandler propertyHandler = new XMLParser.ElementHandler(PROPERTY_ELEMENT, true) { + private ElementHandler propertyHandler = new XMLParser.ElementHandler(PROPERTY_ELEMENT, true) { @Override - public Property start() throws SAXException { - String value = ""; - String name = readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern(); - return getParentObject().getProperties().setProperty(name, value); + public String start() throws SAXException { + return readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern(); } @Override public void end(String text) { - getObject().setValue(text.trim().intern()); + getParentObject().getProperties().setProperty(getObject(), text.trim().intern()); } }; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java index c5b794fce2f..b9053ec30ac 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java @@ -67,7 +67,7 @@ public class Printer { private void export(XMLWriter writer, Group g) throws IOException { Properties attributes = new Properties(); - attributes.add(new Property("difference", Boolean.toString(true))); + attributes.setProperty("difference", Boolean.toString(true)); writer.startTag(Parser.GROUP_ELEMENT, attributes); writer.writeProperties(g.getProperties()); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java index 1efcd06dec9..24cd0f7d3be 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java @@ -25,7 +25,7 @@ package com.sun.hotspot.igv.data.serialization; import com.sun.hotspot.igv.data.Property; import com.sun.hotspot.igv.data.Properties; -import java.util.Hashtable; +import java.util.HashMap; import java.util.Stack; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; @@ -89,7 +89,7 @@ public class XMLParser implements ContentHandler { private Attributes attr; private StringBuilder currentText; private ParseMonitor monitor; - private Hashtable> hashtable; + private HashMap> hashtable; private boolean needsText; private ElementHandler parentElement; @@ -110,7 +110,7 @@ public class XMLParser implements ContentHandler { } public ElementHandler(String name, boolean needsText) { - this.hashtable = new Hashtable>(); + this.hashtable = new HashMap>(); this.name = name; this.needsText = needsText; } @@ -153,7 +153,7 @@ public class XMLParser implements ContentHandler { for (int i = 0; i < length; i++) { String val = attr.getValue(i).intern(); String localName = attr.getLocalName(i).intern(); - p.add(new Property(val, localName)); + p.setProperty(val, localName); } } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java index e112dbf4f07..8ff54f75d41 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java @@ -89,7 +89,7 @@ public class XMLWriter extends Writer { inner.write("<" + name); elementStack.push(name); - for (Property p : attributes.getProperties()) { + for (Property p : attributes) { inner.write(" " + p.getName() + "=\""); write(p.getValue().toCharArray()); inner.write("\""); @@ -101,7 +101,7 @@ public class XMLWriter extends Writer { public void simpleTag(String name, Properties attributes) throws IOException { inner.write("<" + name); - for (Property p : attributes.getProperties()) { + for (Property p : attributes) { inner.write(" " + p.getName() + "=\""); write(p.getValue().toCharArray()); inner.write("\""); @@ -111,13 +111,13 @@ public class XMLWriter extends Writer { } public void writeProperties(Properties props) throws IOException { - if (props.getProperties().size() == 0) { + if (props.getProperties().hasNext() == false) { return; } startTag(Parser.PROPERTIES_ELEMENT); - for (Property p : props.getProperties()) { + for (Property p : props) { startTag(Parser.PROPERTY_ELEMENT, new Properties(Parser.PROPERTY_NAME_PROPERTY, p.getName())); this.write(p.getValue().toCharArray()); endTag(); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java b/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java index 335344eb77b..650ee5f63ed 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java @@ -29,6 +29,7 @@ import com.sun.hotspot.igv.data.InputEdge; import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.InputNode; import com.sun.hotspot.igv.data.Property; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -124,8 +125,8 @@ public class Difference { inputNodeMap.put(n, n2); } - Set edgesA = a.getEdges(); - Set edgesB = b.getEdges(); + Collection edgesA = a.getEdges(); + Collection edgesB = b.getEdges(); Set newEdges = new HashSet(); @@ -182,7 +183,7 @@ public class Difference { public double getValue() { double result = 0.0; - for (Property p : n1.getProperties().getProperties()) { + for (Property p : n1.getProperties()) { double faktor = 1.0; for (String forbidden : IGNORE_PROPERTIES) { if (p.getName().equals(forbidden)) { @@ -287,34 +288,34 @@ public class Difference { private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) { boolean difference = false; - for (Property p : otherNode.getProperties().getProperties()) { - String s = firstNode.getProperties().getProperty(p.getName()); + for (Property p : otherNode.getProperties()) { + String s = firstNode.getProperties().get(p.getName()); if (!p.getValue().equals(s)) { difference = true; - n.getProperties().add(new Property(OLD_PREFIX + p.getName(), p.getValue())); + n.getProperties().setProperty(OLD_PREFIX + p.getName(), p.getValue()); } } - for (Property p : firstNode.getProperties().getProperties()) { - String s = otherNode.getProperties().getProperty(p.getName()); + for (Property p : firstNode.getProperties()) { + String s = otherNode.getProperties().get(p.getName()); if (s == null && p.getValue().length() > 0) { difference = true; - n.getProperties().add(new Property(OLD_PREFIX + p.getName(), "")); + n.getProperties().setProperty(OLD_PREFIX + p.getName(), ""); } } if (difference) { - n.getProperties().add(new Property(PROPERTY_STATE, VALUE_CHANGED)); + n.getProperties().setProperty(PROPERTY_STATE, VALUE_CHANGED); } else { - n.getProperties().add(new Property(PROPERTY_STATE, VALUE_SAME)); + n.getProperties().setProperty(PROPERTY_STATE, VALUE_SAME); } } private static void markAsDeleted(InputNode n) { - n.getProperties().add(new Property(PROPERTY_STATE, VALUE_DELETED)); + n.getProperties().setProperty(PROPERTY_STATE, VALUE_DELETED); } private static void markAsNew(InputNode n) { - n.getProperties().add(new Property(PROPERTY_STATE, VALUE_NEW)); + n.getProperties().setProperty(PROPERTY_STATE, VALUE_NEW); } } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/manifest.mf b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/manifest.mf index 185ff360536..da8d443b487 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/manifest.mf +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/manifest.mf @@ -1,6 +1,6 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.filter -OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.filter +OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java index 762d8d2a22e..18a8841f66d 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java @@ -25,7 +25,6 @@ package com.sun.hotspot.igv.filter; import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.data.Property; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -56,7 +55,7 @@ public class CustomFilter extends AbstractFilter { public CustomFilter(String name, String code) { this.name = name; this.code = code; - getProperties().add(new Property("name", name)); + getProperties().setProperty("name", name); } public String getName() { diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java index e4c2554bda5..baf1ca8c723 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java @@ -56,8 +56,8 @@ public class SplitFilter extends AbstractFilter { for (OutputSlot os : f.getOutputSlots()) { for (Connection c : os.getConnections()) { InputSlot is = c.getInputSlot(); - is.setName(f.getProperties().getProperty("dump_spec")); - String s = f.getProperties().getProperty("short_name"); + is.setName(f.getProperties().get("dump_spec")); + String s = f.getProperties().get("short_name"); if (s != null) { is.setShortName(s); } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java index 00d48f6e926..2584b44fd91 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java @@ -35,7 +35,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -126,7 +126,7 @@ public class Diagram { d.updateBlocks(); Collection nodes = graph.getNodes(); - Hashtable figureHash = new Hashtable(); + HashMap figureHash = new HashMap(); for (InputNode n : nodes) { Figure f = d.createFigure(); f.getSource().addSourceNode(n); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java index cfb913ca318..d61bb286d3f 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java @@ -42,7 +42,7 @@ import java.util.Set; * * @author Thomas Wuerthinger */ -public class Figure extends Properties.Object implements Source.Provider, Vertex { +public class Figure extends Properties.Entity implements Source.Provider, Vertex { public static final int INSET = 6; public static final int SLOT_WIDTH = 10; diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java index 98dbe392c21..ada9d678617 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java @@ -26,7 +26,7 @@ package com.sun.hotspot.igv.hierarchicallayout; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Hashtable; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Queue; @@ -37,13 +37,13 @@ import java.util.Queue; */ public class Graph { - private Hashtable> nodes; - private Hashtable> edges; + private HashMap> nodes; + private HashMap> edges; private List> nodeList; public Graph() { - nodes = new Hashtable>(); - edges = new Hashtable>(); + nodes = new HashMap>(); + edges = new HashMap>(); nodeList = new ArrayList>(); } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java index 1dc1b3691d7..37b05d245c1 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java @@ -25,7 +25,7 @@ package com.sun.hotspot.igv.hierarchicallayout; import java.awt.Point; import java.awt.Rectangle; -import java.util.Hashtable; +import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.ArrayList; @@ -69,19 +69,19 @@ public class HierarchicalClusterLayoutManager implements LayoutManager { assert graph.verify(); - Hashtable> lists = new Hashtable>(); - Hashtable> listsConnection = new Hashtable>(); - Hashtable> clusterInputSlotHash = new Hashtable>(); - Hashtable> clusterOutputSlotHash = new Hashtable>(); + HashMap> lists = new HashMap>(); + HashMap> listsConnection = new HashMap>(); + HashMap> clusterInputSlotHash = new HashMap>(); + HashMap> clusterOutputSlotHash = new HashMap>(); - Hashtable clusterNodes = new Hashtable(); - Hashtable> clusterInputSlotSet = new Hashtable>(); - Hashtable> clusterOutputSlotSet = new Hashtable>(); + HashMap clusterNodes = new HashMap(); + HashMap> clusterInputSlotSet = new HashMap>(); + HashMap> clusterOutputSlotSet = new HashMap>(); Set clusterEdges = new HashSet(); Set interClusterEdges = new HashSet(); - Hashtable linkClusterOutgoingConnection = new Hashtable(); - Hashtable linkInterClusterConnection = new Hashtable(); - Hashtable linkClusterIngoingConnection = new Hashtable(); + HashMap linkClusterOutgoingConnection = new HashMap(); + HashMap linkInterClusterConnection = new HashMap(); + HashMap linkClusterIngoingConnection = new HashMap(); Set clusterNodeSet = new HashSet(); Set cluster = graph.getClusters(); @@ -89,8 +89,8 @@ public class HierarchicalClusterLayoutManager implements LayoutManager { for (Cluster c : cluster) { lists.put(c, new ArrayList()); listsConnection.put(c, new ArrayList()); - clusterInputSlotHash.put(c, new Hashtable()); - clusterOutputSlotHash.put(c, new Hashtable()); + clusterInputSlotHash.put(c, new HashMap()); + clusterOutputSlotHash.put(c, new HashMap()); clusterOutputSlotSet.put(c, new TreeSet()); clusterInputSlotSet.put(c, new TreeSet()); ClusterNode cn = new ClusterNode(c, "" + z); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java index ac262c95e74..50edc14a864 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java @@ -24,7 +24,7 @@ package com.sun.hotspot.igv.layout; import java.util.HashSet; -import java.util.Hashtable; +import java.util.HashMap; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -37,9 +37,9 @@ public class LayoutGraph { private Set links; private SortedSet vertices; - private Hashtable> inputPorts; - private Hashtable> outputPorts; - private Hashtable> portLinks; + private HashMap> inputPorts; + private HashMap> outputPorts; + private HashMap> portLinks; public LayoutGraph(Set links) { this(links, new HashSet()); @@ -50,9 +50,9 @@ public class LayoutGraph { assert verify(); vertices = new TreeSet(); - portLinks = new Hashtable>(); - inputPorts = new Hashtable>(); - outputPorts = new Hashtable>(); + portLinks = new HashMap>(); + inputPorts = new HashMap>(); + outputPorts = new HashMap>(); for (Link l : links) { Port p = l.getFrom(); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/README b/hotspot/src/share/tools/IdealGraphVisualizer/README index 80e16329506..5c9a16601bc 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/README +++ b/hotspot/src/share/tools/IdealGraphVisualizer/README @@ -5,21 +5,16 @@ of Linz in Austria and has been included as part of hotspot since that was the primary target of the tool. The tool itself is fairly general with only a few modules that contain C2 specific elements. -The tool is built on top of the NetBeans 6.0 rich client +The tool is built on top of the NetBeans 6.1 rich client infrastructure and so requires NetBeans to build. It currently requires Java 6 to run as it needs support for JavaScript for its filtering mechanism and assumes it's built into the platform. It -should build out of the box whit NetBeans 6 and Java 6 or later. It's -possible to run it on 1.5 by including Rhino on the classpath though -that currently isn't working correctly. Support for exporting graphs -as SVG can be enabled by adding batik to the classpath which isn't -included by default. - -It can be built on top of NetBeans 6.1 if you change the required -modules to be platform8 instead of platform7. The tool could run on -JDK 1.5 with some reworking of the how the JavaScript support is -enabled but currently it requires some tweaking of the setup. This -will be fixed in a later setup. +should build out of the box with NetBeans 6.1 and Java 6 or later. +It's possible to run it on 1.5 by including Rhino on the classpath +though that currently isn't working correctly. Support for exporting +graphs as SVG can be enabled by adding batik to the classpath which +isn't included by default. It can be built on top of NetBeans 6.0 if +you change the required modules to be platform7 instead of platform8. The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=# where # is: diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java index f058edda6ae..ab7da78f2c4 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java @@ -36,11 +36,11 @@ import org.openide.nodes.Sheet; */ public class PropertiesSheet { - public static void initializeSheet(Properties properties, Sheet s) { + public static void initializeSheet(final Properties properties, Sheet s) { Sheet.Set set1 = Sheet.createPropertiesSet(); set1.setDisplayName("Properties"); - for (final Property p : properties.getProperties()) { + for (final Property p : properties) { Node.Property prop = new Node.Property(String.class) { @Override @@ -60,7 +60,7 @@ public class PropertiesSheet { @Override public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - p.setValue(arg0); + properties.setProperty(p.getName(), arg0); } }; prop.setName(p.getName()); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java index 71766ec3b67..a179d1ee08c 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java @@ -65,13 +65,19 @@ public class RangeSliderModel implements ChangedEventProvider public RangeSliderModel(List positions) { assert positions.size() > 0; - this.positions = positions; this.changedEvent = new ChangedEvent(this); this.colorChangedEvent = new ChangedEvent(this); + setPositions(positions); + } + + protected void setPositions(List positions) { + this.positions = positions; colors = new ArrayList(); for (int i = 0; i < positions.size(); i++) { colors.add(Color.black); } + changedEvent.fire(); + colorChangedEvent.fire(); } public void setColors(List colors) { diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java index 2ee3067acfe..7ebfbbe866a 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java @@ -63,7 +63,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -104,10 +104,10 @@ import org.openide.util.lookup.InstanceContent; */ public class DiagramScene extends Scene implements ChangedListener { - private Hashtable figureWidgets; - private Hashtable slotWidgets; - private Hashtable connectionWidgets; - private Hashtable blockWidgets; + private HashMap figureWidgets; + private HashMap slotWidgets; + private HashMap connectionWidgets; + private HashMap blockWidgets; private Widget hoverWidget; private WidgetAction hoverAction; private List selectedWidgets; @@ -414,7 +414,7 @@ public class DiagramScene extends Scene implements ChangedListener(); + blockWidgets = new HashMap(); boolean b = this.getUndoRedoEnabled(); this.setUndoRedoEnabled(false); @@ -543,9 +543,9 @@ public class DiagramScene extends Scene implements ChangedListener(); - slotWidgets = new Hashtable(); - connectionWidgets = new Hashtable(); + figureWidgets = new HashMap(); + slotWidgets = new HashMap(); + connectionWidgets = new HashMap(); WidgetAction selectAction = new ExtendedSelectAction(selectProvider); Diagram d = getModel().getDiagramToView(); diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java index e374873b584..5d1da8ceacf 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java @@ -55,6 +55,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene private FilterChain filterChain; private FilterChain sequenceFilterChain; private Diagram diagram; + private ChangedEvent groupChangedEvent; private ChangedEvent diagramChangedEvent; private ChangedEvent viewChangedEvent; private ChangedEvent viewPropertiesChangedEvent; @@ -67,6 +68,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene } }; + @Override public DiagramViewModel copy() { DiagramViewModel result = new DiagramViewModel(group, filterChain, sequenceFilterChain); result.setData(this); @@ -79,6 +81,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene boolean viewChanged = false; boolean viewPropertiesChanged = false; + boolean groupChanged = (group == newModel.group); this.group = newModel.group; diagramChanged |= (filterChain != newModel.filterChain); this.filterChain = newModel.filterChain; @@ -97,6 +100,10 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull); this.showNodeHull = newModel.showNodeHull; + if(groupChanged) { + groupChangedEvent.fire(); + } + if (diagramChanged) { diagramChangedEvent.fire(); } @@ -143,11 +150,38 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene diagramChangedEvent = new ChangedEvent(this); viewChangedEvent = new ChangedEvent(this); viewPropertiesChangedEvent = new ChangedEvent(this); + groupChangedEvent = new ChangedEvent(this); + groupChangedEvent.addListener(groupChangedListener); + groupChangedEvent.fire(); filterChain.getChangedEvent().addListener(filterChainChangedListener); sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener); } + private final ChangedListener groupChangedListener = new ChangedListener() { + + private Group oldGroup; + + public void changed(DiagramViewModel source) { + if(oldGroup != null) { + oldGroup.getChangedEvent().removeListener(groupContentChangedListener); + } + group.getChangedEvent().addListener(groupContentChangedListener); + oldGroup = group; + } + }; + + + private final ChangedListener groupContentChangedListener = new ChangedListener() { + + public void changed(Group source) { + assert source == group; + setPositions(calculateStringList(source)); + setSelectedNodes(selectedNodes); + } + + }; + public ChangedEvent getDiagramChangedEvent() { return diagramChangedEvent; } @@ -268,7 +302,10 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene } public InputGraph getSecondGraph() { - return group.getGraphs().get(getSecondPosition()); + List graphs = group.getGraphs(); + if (graphs.size() >= getSecondPosition()) + return group.getGraphs().get(getSecondPosition()); + return getFirstGraph(); } public void selectGraph(InputGraph g) { diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java index 7d45f1b35c6..961dc54d882 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java +++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java @@ -67,7 +67,7 @@ class FindPanel extends JPanel implements KeyListener { for (Figure f : figures) { Properties prop = f.getProperties(); - for (Property p : prop.getProperties()) { + for (Property p : prop) { if (!propertyNames.contains(p.getName())) { propertyNames.add(p.getName()); } diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties index 4768730f129..881365d0eda 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties +++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties @@ -1,16 +1,16 @@ # Deprecated since 5.0u1; for compatibility with 5.0: disabled.clusters=\ apisupport1,\ + gsf1,\ harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 + ide9,\ + java2,\ + nb6.1,\ + profiler3 disabled.modules=\ org.netbeans.core.execution,\ org.netbeans.core.multiview,\ org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ org.netbeans.modules.autoupdate.services,\ org.netbeans.modules.autoupdate.ui,\ org.netbeans.modules.core.kit,\ @@ -24,6 +24,6 @@ disabled.modules=\ org.openide.execution,\ org.openide.util.enumerations enabled.clusters=\ - platform7 + platform8 nbjdk.active=default nbplatform.active=default diff --git a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties index 1b524d231f3..b00f22d78fc 100644 --- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties +++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties @@ -15,7 +15,6 @@ modules=\ ${project.com.sun.hotspot.igv.difference}:\ ${project.com.sun.hotspot.igv.settings}:\ ${project.com.sun.hotspot.igv.util}:\ - ${project.com.sun.hotspot.igv.rhino}:\ ${project.com.sun.hotspot.igv.svg}:\ ${project.com.sun.hotspot.connection}:\ ${project.com.sun.hotspot.igv.servercompilerscheduler}:\ @@ -31,10 +30,10 @@ project.com.sun.hotspot.igv.filterwindow=FilterWindow project.com.sun.hotspot.igv.graph=Graph project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout project.com.sun.hotspot.igv.layout=Layout -project.com.sun.hotspot.igv.rhino=RhinoScriptEngineProxy project.com.sun.hotspot.igv.servercompilerscheduler=ServerCompiler project.com.sun.hotspot.igv.settings=Settings project.com.sun.hotspot.igv.svg=BatikSVGProxy project.com.sun.hotspot.igv.view=View project.com.sun.hotspot.igv.util=Util -run.args = -server -J-Xms64m -J-Xmx512m -J-da +run.args = -J-server -J-Xms64m -J-Xmx1g -J-da +run.args.extra = -J-server -J-Xms64m -J-Xmx1g -J-da diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index 6ebef89f27f..c266df104c8 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -33,7 +33,6 @@ ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc) _globalNames(archDesc.globalNames()) { _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file _AD._warnings = 0; // No warnings either - _linenum = 0; // Will increment to first line _curline = _ptr = NULL; // No pointers into buffer yet _preproc_depth = 0; @@ -76,7 +75,7 @@ ADLParser::~ADLParser() { } if (!_AD._quiet_mode) fprintf(stderr,"-----------------------------------------------------------------------------\n"); - _AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine + _AD._TotalLines += linenum()-1; // -1 for overshoot in "nextline" routine // Write out information we have stored // // UNIXism == fsync(stderr); @@ -148,7 +147,7 @@ void ADLParser::instr_parse(void) { if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL ) return; instr = new InstructForm(ident); // Create new instruction form - instr->_linenum = _linenum; + instr->_linenum = linenum(); _globalNames.Insert(ident, instr); // Add name to the name table // Debugging Stuff if (_AD._adl_debug > 1) @@ -404,7 +403,7 @@ void ADLParser::oper_parse(void) { if( (ident = get_unique_ident(_globalNames,"operand")) == NULL ) return; oper = new OperandForm(ident); // Create new operand form - oper->_linenum = _linenum; + oper->_linenum = linenum(); _globalNames.Insert(ident, oper); // Add name to the name table // Debugging Stuff @@ -774,7 +773,7 @@ void ADLParser::reg_parse(void) { // Create the RegisterForm for the architecture description. RegisterForm *regBlock = new RegisterForm(); // Build new Source object - regBlock->_linenum = _linenum; + regBlock->_linenum = linenum(); _AD.addForm(regBlock); skipws(); // Skip leading whitespace @@ -847,7 +846,7 @@ void ADLParser::enc_class_parse(void) { } EncClass *encoding = _AD._encode->add_EncClass(ec_name); - encoding->_linenum = _linenum; + encoding->_linenum = linenum(); skipws(); // Skip leading whitespace // Check for optional parameter list @@ -905,7 +904,7 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) { // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block if (_AD._adlocation_debug) { const char* file = _AD._ADL_file._name; - int line = _linenum; + int line = linenum(); char* location = (char *)malloc(strlen(file) + 100); sprintf(location, "#line %d \"%s\"\n", line, file); encoding->add_code(location); @@ -2776,7 +2775,7 @@ InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) { assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); EncClass *encoding = _AD._encode->add_EncClass(ec_name); - encoding->_linenum = _linenum; + encoding->_linenum = linenum(); // synthesize the arguments list for the enc_class from the // arguments to the instruct definition. @@ -2852,7 +2851,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) { skipws(); InsEncode *encrule = new InsEncode(); // Encode class for instruction - encrule->_linenum = _linenum; + encrule->_linenum = linenum(); char *ec_name = NULL; // String representation of encode rule // identifier is optional. while (_curchar != ')') { @@ -3203,6 +3202,12 @@ Interface *ADLParser::cond_interface_parse(void) { char *greater_equal; char *less_equal; char *greater; + const char *equal_format = "eq"; + const char *not_equal_format = "ne"; + const char *less_format = "lt"; + const char *greater_equal_format = "ge"; + const char *less_equal_format = "le"; + const char *greater_format = "gt"; if (_curchar != '%') { parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); @@ -3222,22 +3227,22 @@ Interface *ADLParser::cond_interface_parse(void) { return NULL; } if ( strcmp(field,"equal") == 0 ) { - equal = interface_field_parse(); + equal = interface_field_parse(&equal_format); } else if ( strcmp(field,"not_equal") == 0 ) { - not_equal = interface_field_parse(); + not_equal = interface_field_parse(¬_equal_format); } else if ( strcmp(field,"less") == 0 ) { - less = interface_field_parse(); + less = interface_field_parse(&less_format); } else if ( strcmp(field,"greater_equal") == 0 ) { - greater_equal = interface_field_parse(); + greater_equal = interface_field_parse(&greater_equal_format); } else if ( strcmp(field,"less_equal") == 0 ) { - less_equal = interface_field_parse(); + less_equal = interface_field_parse(&less_equal_format); } else if ( strcmp(field,"greater") == 0 ) { - greater = interface_field_parse(); + greater = interface_field_parse(&greater_format); } else { parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); @@ -3252,14 +3257,18 @@ Interface *ADLParser::cond_interface_parse(void) { next_char(); // Skip '}' // Construct desired object and return - Interface *inter = new CondInterface(equal, not_equal, less, greater_equal, - less_equal, greater); + Interface *inter = new CondInterface(equal, equal_format, + not_equal, not_equal_format, + less, less_format, + greater_equal, greater_equal_format, + less_equal, less_equal_format, + greater, greater_format); return inter; } //------------------------------interface_field_parse-------------------------- -char *ADLParser::interface_field_parse(void) { +char *ADLParser::interface_field_parse(const char ** format) { char *iface_field = NULL; // Get interface field @@ -3280,6 +3289,32 @@ char *ADLParser::interface_field_parse(void) { return NULL; } skipws(); + if (format != NULL && _curchar == ',') { + next_char(); + skipws(); + if (_curchar != '"') { + parse_err(SYNERR, "Missing '\"' in field format .\n"); + return NULL; + } + next_char(); + char *start = _ptr; // Record start of the next string + while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { + if (_curchar == '\\') next_char(); // superquote + if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! + next_char(); + } + if (_curchar != '"') { + parse_err(SYNERR, "Missing '\"' at end of field format .\n"); + return NULL; + } + // If a string was found, terminate it and record in FormatRule + if ( start != _ptr ) { + *_ptr = '\0'; // Terminate the string + *format = start; + } + next_char(); + skipws(); + } if (_curchar != ')') { parse_err(SYNERR, "Missing ')' after interface field.\n"); return NULL; @@ -3342,6 +3377,12 @@ FormatRule* ADLParser::format_parse(void) { next_char(); // Move past the '{' skipws(); + if (_curchar == '$') { + char* ident = get_rep_var_ident(); + if (strcmp(ident, "$$template") == 0) return template_parse(); + parse_err(SYNERR, "Unknown \"%s\" directive in format", ident); + return NULL; + } // Check for the opening '"' inside the format description if ( _curchar == '"' ) { next_char(); // Move past the initial '"' @@ -3433,6 +3474,131 @@ FormatRule* ADLParser::format_parse(void) { } +//------------------------------template_parse----------------------------------- +FormatRule* ADLParser::template_parse(void) { + char *desc = NULL; + FormatRule *format = (new FormatRule(desc)); + + skipws(); + while ( (_curchar != '%') && (*(_ptr+1) != '}') ) { + + // (1) + // Check if there is a string to pass through to output + char *start = _ptr; // Record start of the next string + while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) { + // If at the start of a comment, skip past it + if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) { + skipws_no_preproc(); + } else { + // ELSE advance to the next character, or start of the next line + next_char_or_line(); + } + } + // If a string was found, terminate it and record in EncClass + if ( start != _ptr ) { + *_ptr = '\0'; // Terminate the string + // Add flag to _strings list indicating we should check _rep_vars + format->_strings.addName(NameList::_signal2); + format->_strings.addName(start); + } + + // (2) + // If we are at a replacement variable, + // copy it and record in EncClass + if ( _curchar == '$' ) { + // Found replacement Variable + char *rep_var = get_rep_var_ident_dup(); + if (strcmp(rep_var, "$emit") == 0) { + // switch to normal format parsing + next_char(); + next_char(); + skipws(); + // Check for the opening '"' inside the format description + if ( _curchar == '"' ) { + next_char(); // Move past the initial '"' + if( _curchar == '"' ) { // Handle empty format string case + *_ptr = '\0'; // Terminate empty string + format->_strings.addName(_ptr); + } + + // Collect the parts of the format description + // (1) strings that are passed through to tty->print + // (2) replacement/substitution variable, preceeded by a '$' + // (3) multi-token ANSIY C style strings + while ( true ) { + if ( _curchar == '%' || _curchar == '\n' ) { + parse_err(SYNERR, "missing '\"' at end of format block"); + return NULL; + } + + // (1) + // Check if there is a string to pass through to output + char *start = _ptr; // Record start of the next string + while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) { + if (_curchar == '\\') next_char(); // superquote + if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented! + next_char(); + } + // If a string was found, terminate it and record in FormatRule + if ( start != _ptr ) { + *_ptr = '\0'; // Terminate the string + format->_strings.addName(start); + } + + // (2) + // If we are at a replacement variable, + // copy it and record in FormatRule + if ( _curchar == '$' ) { + next_char(); // Move past the '$' + char* rep_var = get_ident(); // Nil terminate the variable name + rep_var = strdup(rep_var);// Copy the string + *_ptr = _curchar; // and replace Nil with original character + format->_rep_vars.addName(rep_var); + // Add flag to _strings list indicating we should check _rep_vars + format->_strings.addName(NameList::_signal); + } + + // (3) + // Allow very long strings to be broken up, + // using the ANSI C syntax "foo\n" "bar" + if ( _curchar == '"') { + next_char(); // Move past the '"' + skipws(); // Skip white space before next string token + if ( _curchar != '"') { + break; + } else { + // Found one. Skip both " and the whitespace in between. + next_char(); + } + } + } // end while part of format description + } + } else { + // Add flag to _strings list indicating we should check _rep_vars + format->_rep_vars.addName(rep_var); + // Add flag to _strings list indicating we should check _rep_vars + format->_strings.addName(NameList::_signal3); + } + } // end while part of format description + } + + skipws(); + // Past format description, at '%' + if ( _curchar != '%' || *(_ptr+1) != '}' ) { + parse_err(SYNERR, "missing '%}' at end of format block"); + return NULL; + } + next_char(); // Move past the '%' + next_char(); // Move past the '}' + + // Debug Stuff + if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc); + + skipws(); + return format; +} + + //------------------------------effect_parse----------------------------------- void ADLParser::effect_parse(InstructForm *instr) { char* desc = NULL; @@ -3777,7 +3943,7 @@ char* ADLParser::find_cpp_block(const char* description) { skipws_no_preproc(); // Skip leading whitespace cppBlock = _ptr; // Point to start of expression const char* file = _AD._ADL_file._name; - int line = _linenum; + int line = linenum(); next = _ptr + 1; while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) { next_char_or_line(); @@ -4297,11 +4463,11 @@ void ADLParser::parse_err(int flag, const char *fmt, ...) { va_start(args, fmt); if (flag == 1) - _AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); + _AD._syntax_errs += _AD.emit_msg(0, flag, linenum(), fmt, args); else if (flag == 2) - _AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args); + _AD._semantic_errs += _AD.emit_msg(0, flag, linenum(), fmt, args); else - _AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args); + _AD._warnings += _AD.emit_msg(0, flag, linenum(), fmt, args); int error_char = _curchar; char* error_ptr = _ptr+1; @@ -4515,7 +4681,7 @@ void ADLParser::next_char_or_line() { //---------------------------next_line----------------------------------------- void ADLParser::next_line() { - _curline = _buf.get_line(); _linenum++; + _curline = _buf.get_line(); } //-------------------------is_literal_constant--------------------------------- diff --git a/hotspot/src/share/vm/adlc/adlparse.hpp b/hotspot/src/share/vm/adlc/adlparse.hpp index 853a104f7cd..42329ac279e 100644 --- a/hotspot/src/share/vm/adlc/adlparse.hpp +++ b/hotspot/src/share/vm/adlc/adlparse.hpp @@ -70,7 +70,6 @@ class ADLParser { protected: char *_curline; // Start of current line char *_ptr; // Pointer into current location in File Buffer - int _linenum; // Count of line numbers seen so far char _curchar; // Current character from buffer FormDict &_globalNames; // Global names @@ -160,9 +159,10 @@ protected: Interface *interface_parse(); // Parse operand interface rule Interface *mem_interface_parse(); // Parse memory interface rule Interface *cond_interface_parse(); // Parse conditional interface rule - char *interface_field_parse();// Parse field contents + char *interface_field_parse(const char** format = NULL);// Parse field contents FormatRule *format_parse(void); // Parse format rule + FormatRule *template_parse(void); // Parse format rule void effect_parse(InstructForm *instr); // Parse effect rule ExpandRule *expand_parse(InstructForm *instr); // Parse expand rule RewriteRule *rewrite_parse(void); // Parse rewrite rule @@ -263,7 +263,7 @@ public: void parse(void); // Do the parsing & build forms lists - int getlines( ) { return _linenum; } + int linenum() { return _buf.linenum(); } static bool is_literal_constant(const char *hex_string); static bool is_hex_digit(char digit); diff --git a/hotspot/src/share/vm/adlc/filebuff.cpp b/hotspot/src/share/vm/adlc/filebuff.cpp index 502354edcf0..6fe23fcbae7 100644 --- a/hotspot/src/share/vm/adlc/filebuff.cpp +++ b/hotspot/src/share/vm/adlc/filebuff.cpp @@ -41,6 +41,7 @@ FileBuff::FileBuff( BufferedFile *fptr, ArchDesc& archDesc) : _fp(fptr), _AD(arc exit(1); // Exit on seek error } _filepos = ftell(_fp->_fp); // Reset current file position + _linenum = 0; _bigbuf = new char[_bufferSize]; // Create buffer to hold text for parser if( !_bigbuf ) { @@ -76,6 +77,7 @@ char *FileBuff::get_line(void) { // Check for end of file & return NULL if (_bufeol >= _bufmax) return NULL; + _linenum++; retval = ++_bufeol; // return character following end of previous line if (*retval == '\0') return NULL; // Check for EOF sentinal // Search for newline character which must end each line diff --git a/hotspot/src/share/vm/adlc/filebuff.hpp b/hotspot/src/share/vm/adlc/filebuff.hpp index fdfa985db4c..c36fdbaf3fa 100644 --- a/hotspot/src/share/vm/adlc/filebuff.hpp +++ b/hotspot/src/share/vm/adlc/filebuff.hpp @@ -51,6 +51,7 @@ class FileBuff { int _err; // Error flag for file seek/read operations long _filepos; // Current offset from start of file + int _linenum; ArchDesc& _AD; // Reference to Architecture Description @@ -66,6 +67,7 @@ class FileBuff { // This returns a pointer to the start of the current line in the buffer, // and increments bufeol and filepos to point at the end of that line. char *get_line(void); + int linenum() const { return _linenum; } // This converts a pointer into the buffer to a file offset. It only works // when the pointer is valid (i.e. just obtained from getline()). diff --git a/hotspot/src/share/vm/adlc/forms.cpp b/hotspot/src/share/vm/adlc/forms.cpp index e9d7de211ea..e2083c68259 100644 --- a/hotspot/src/share/vm/adlc/forms.cpp +++ b/hotspot/src/share/vm/adlc/forms.cpp @@ -35,6 +35,8 @@ Arena *Form::generate_arena() { //------------------------------NameList--------------------------------------- // reserved user-defined string const char *NameList::_signal = "$$SIGNAL$$"; +const char *NameList::_signal2 = "$$SIGNAL2$$"; +const char *NameList::_signal3 = "$$SIGNAL3$$"; // Constructor and Destructor NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) { diff --git a/hotspot/src/share/vm/adlc/forms.hpp b/hotspot/src/share/vm/adlc/forms.hpp index c510ac43aef..bf930b8e6da 100644 --- a/hotspot/src/share/vm/adlc/forms.hpp +++ b/hotspot/src/share/vm/adlc/forms.hpp @@ -329,6 +329,8 @@ protected: public: static const char *_signal; // reserved user-defined string + static const char *_signal2; // reserved user-defined string + static const char *_signal3; // reserved user-defined string enum { Not_in_list = -1 }; void addName(const char *name); diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index 2957ae39fc8..fb91d83d2f6 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -1574,10 +1574,10 @@ Opcode::opcode_type Opcode::as_opcode_type(const char *param) { return Opcode::NOT_AN_OPCODE; } -void Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) { +bool Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) { // Default values previously provided by MachNode::primary()... - const char *description = "default_opcode()"; - const char *value = "-1"; + const char *description = NULL; + const char *value = NULL; // Check if user provided any opcode definitions if( this != NULL ) { // Update 'value' if user provided a definition in the instruction @@ -1599,7 +1599,10 @@ void Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) { break; } } - fprintf(fp, "(%s /*%s*/)", value, description); + if (value != NULL) { + fprintf(fp, "(%s /*%s*/)", value, description); + } + return value != NULL; } void Opcode::dump() { @@ -2610,14 +2613,19 @@ void MemInterface::output(FILE *fp) { } //------------------------------CondInterface---------------------------------- -CondInterface::CondInterface(char *equal, char *not_equal, - char *less, char *greater_equal, - char *less_equal, char *greater) +CondInterface::CondInterface(const char* equal, const char* equal_format, + const char* not_equal, const char* not_equal_format, + const char* less, const char* less_format, + const char* greater_equal, const char* greater_equal_format, + const char* less_equal, const char* less_equal_format, + const char* greater, const char* greater_format) : Interface("COND_INTER"), - _equal(equal), _not_equal(not_equal), - _less(less), _greater_equal(greater_equal), - _less_equal(less_equal), _greater(greater) { - // + _equal(equal), _equal_format(equal_format), + _not_equal(not_equal), _not_equal_format(not_equal_format), + _less(less), _less_format(less_format), + _greater_equal(greater_equal), _greater_equal_format(greater_equal_format), + _less_equal(less_equal), _less_equal_format(less_equal_format), + _greater(greater), _greater_format(greater_format) { } CondInterface::~CondInterface() { // not owner of any character arrays @@ -3316,7 +3324,7 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { "Load8B" ,"Load4B" ,"Load8C" ,"Load4C" ,"Load2C" ,"Load8S", "Load4S","Load2S", "LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned", "LoadPLocked", "LoadLLocked", - "StorePConditional", "StoreLConditional", + "StorePConditional", "StoreIConditional", "StoreLConditional", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", "StoreCM", "ClearArray" diff --git a/hotspot/src/share/vm/adlc/formssel.hpp b/hotspot/src/share/vm/adlc/formssel.hpp index 8ed2885c890..9bcbe636ef7 100644 --- a/hotspot/src/share/vm/adlc/formssel.hpp +++ b/hotspot/src/share/vm/adlc/formssel.hpp @@ -397,7 +397,7 @@ public: void output(FILE *fp); // --------------------------- FILE *output_routines - void print_opcode(FILE *fp, Opcode::opcode_type desired_opcode); + bool print_opcode(FILE *fp, Opcode::opcode_type desired_opcode); }; //------------------------------InsEncode-------------------------------------- @@ -779,10 +779,20 @@ public: const char *_greater_equal; const char *_less_equal; const char *_greater; + const char *_equal_format; + const char *_not_equal_format; + const char *_less_format; + const char *_greater_equal_format; + const char *_less_equal_format; + const char *_greater_format; // Public Methods - CondInterface(char *equal, char *not_equal, char *less, char *greater_equal, - char *less_equal, char *greater); + CondInterface(const char* equal, const char* equal_format, + const char* not_equal, const char* not_equal_format, + const char* less, const char* less_format, + const char* greater_equal, const char* greater_equal_format, + const char* less_equal, const char* less_equal_format, + const char* greater, const char* greater_format); ~CondInterface(); void dump(); diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index eb33e67b376..dbc287b1d1a 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -1619,6 +1619,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { } // Iterate over the new instruction's operands + int prev_pos = -1; for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) { // Use 'parameter' at current position in list of new instruction's formals // instead of 'opid' when looking up info internal to new_inst @@ -1642,6 +1643,18 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { // ins = (InstructForm *) _globalNames[new_id]; exp_pos = node->operand_position_format(opid); assert(exp_pos != -1, "Bad expand rule"); + if (prev_pos > exp_pos && expand_instruction->_matrule != NULL) { + // For the add_req calls below to work correctly they need + // to added in the same order that a match would add them. + // This means that they would need to be in the order of + // the components list instead of the formal parameters. + // This is a sort of hidden invariant that previously + // wasn't checked and could lead to incorrectly + // constructed nodes. + syntax_err(node->_linenum, "For expand in %s to work, parameter declaration order in %s must follow matchrule\n", + node->_ident, new_inst->_ident); + } + prev_pos = exp_pos; new_pos = new_inst->operand_position(parameter,Component::USE); if (new_pos != -1) { @@ -2306,7 +2319,12 @@ private: _processing_noninput = false; // A replacement variable, originally '$' if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { - _inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) ); + if (!_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) )) { + // Missing opcode + _AD.syntax_err( _inst._linenum, + "Missing $%s opcode definition in %s, used by encoding %s\n", + rep_var, _inst._ident, _encoding._name); + } } else { // Lookup its position in parameter list @@ -2348,7 +2366,13 @@ private: else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) { // else check if "primary", "secondary", "tertiary" assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); - _inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) ); + if (!_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) )) { + // Missing opcode + _AD.syntax_err( _inst._linenum, + "Missing $%s opcode definition in %s\n", + rep_var, _inst._ident); + + } _constant_status = LITERAL_OUTPUT; } else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) { diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 04cddcd28c8..d2fd489abe9 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -355,17 +355,19 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts, // --------------------------------------------------------------------------- // Generate the format rule for condition codes -static void defineCCodeDump(FILE *fp, int i) { - fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"eq\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"ne\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"le\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"ge\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"lt\");\n",i); - fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"gt\");\n",i); +static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) { + assert(oper != NULL, "what"); + CondInterface* cond = oper->_interface->is_CondInterface(); + fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format); + fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format); + fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format); } // Output code that dumps constant values, increment "i" if type is constant -static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) { +static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) { if (!strcmp(ideal_type, "ConI")) { fprintf(fp," st->print(\"#%%d\", _c%d);\n", i); ++i; @@ -375,7 +377,7 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) { ++i; } else if (!strcmp(ideal_type, "ConN")) { - fprintf(fp," _c%d->dump();\n", i); + fprintf(fp," _c%d->dump_on(st);\n", i); ++i; } else if (!strcmp(ideal_type, "ConL")) { @@ -391,7 +393,7 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) { ++i; } else if (!strcmp(ideal_type, "Bool")) { - defineCCodeDump(fp,i); + defineCCodeDump(oper, fp,i); ++i; } @@ -476,7 +478,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_ } // ALWAYS! Provide a special case output for condition codes. if( oper.is_ideal_bool() ) { - defineCCodeDump(fp,0); + defineCCodeDump(&oper, fp,0); } fprintf(fp,"}\n"); @@ -549,7 +551,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_ } // ALWAYS! Provide a special case output for condition codes. if( oper.is_ideal_bool() ) { - defineCCodeDump(fp,0); + defineCCodeDump(&oper, fp,0); } fprintf(fp, "}\n"); fprintf(fp, "#endif\n"); @@ -583,10 +585,53 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c while( (string = inst._format->_strings.iter()) != NULL ) { fprintf(fp," "); // Check if this is a standard string or a replacement variable - if( string != NameList::_signal ) // Normal string. Pass through. + if( string == NameList::_signal ) { // Replacement variable + const char* rep_var = inst._format->_rep_vars.iter(); + inst.rep_var_format( fp, rep_var); + } else if( string == NameList::_signal3 ) { // Replacement variable in raw text + const char* rep_var = inst._format->_rep_vars.iter(); + const Form *form = inst._localNames[rep_var]; + if (form == NULL) { + fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var); + assert(false, "ShouldNotReachHere()"); + } + OpClassForm *opc = form->is_opclass(); + assert( opc, "replacement variable was not found in local names"); + // Lookup the index position of the replacement variable + int idx = inst.operand_position_format(rep_var); + if ( idx == -1 ) { + assert( strcmp(opc->_ident,"label")==0, "Unimplemented"); + assert( false, "ShouldNotReachHere()"); + } + + if (inst.is_noninput_operand(idx)) { + assert( false, "ShouldNotReachHere()"); + } else { + // Output the format call for this operand + fprintf(fp,"opnd_array(%d)",idx); + } + rep_var = inst._format->_rep_vars.iter(); + inst._format->_strings.iter(); + if ( strcmp(rep_var,"$constant") == 0 && opc->is_operand()) { + Form::DataType constant_type = form->is_operand()->is_base_constant(globals); + if ( constant_type == Form::idealD ) { + fprintf(fp,"->constantD()"); + } else if ( constant_type == Form::idealF ) { + fprintf(fp,"->constantF()"); + } else if ( constant_type == Form::idealL ) { + fprintf(fp,"->constantL()"); + } else { + fprintf(fp,"->constant()"); + } + } else if ( strcmp(rep_var,"$cmpcode") == 0) { + fprintf(fp,"->ccode()"); + } else { + assert( false, "ShouldNotReachHere()"); + } + } else if( string == NameList::_signal2 ) // Raw program text + fputs(inst._format->_strings.iter(), fp); + else fprintf(fp,"st->print(\"%s\");\n", string); - else // Replacement variable - inst.rep_var_format( fp, inst._format->_rep_vars.iter() ); } // Done with all format strings } // Done generating the user-defined portion of the format @@ -1404,7 +1449,7 @@ void ArchDesc::declareClasses(FILE *fp) { oper->_components.reset(); if ((comp = oper->_components.iter()) == NULL) { assert(num_consts == 1, "Bad component list detected.\n"); - i = dump_spec_constant( fp, type, i ); + i = dump_spec_constant( fp, type, i, oper ); // Check that type actually matched assert( i != 0, "Non-constant operand lacks component list."); } // end if NULL @@ -1414,7 +1459,7 @@ void ArchDesc::declareClasses(FILE *fp) { oper->_components.reset(); while((comp = oper->_components.iter()) != NULL) { type = comp->base_type(_globalNames); - i = dump_spec_constant( fp, type, i ); + i = dump_spec_constant( fp, type, i, NULL ); } } // finish line (3) diff --git a/hotspot/src/share/vm/interpreter/bytecodeStream.cpp b/hotspot/src/share/vm/interpreter/bytecodeStream.cpp index 9152907e199..bb051e53049 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeStream.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeStream.cpp @@ -28,8 +28,9 @@ Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) { assert(!is_last_bytecode(), "should have been checked"); // set next bytecode position - address bcp = RawBytecodeStream::bcp(); - int l = Bytecodes::raw_special_length_at(bcp); + address bcp = RawBytecodeStream::bcp(); + address end = method()->code_base() + end_bci(); + int l = Bytecodes::raw_special_length_at(bcp, end); if (l <= 0 || (_bci + l) > _end_bci) { code = Bytecodes::_illegal; } else { @@ -39,8 +40,12 @@ Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) { _is_wide = false; // check for special (uncommon) cases if (code == Bytecodes::_wide) { - code = (Bytecodes::Code)bcp[1]; - _is_wide = true; + if (bcp + 1 >= end) { + code = Bytecodes::_illegal; + } else { + code = (Bytecodes::Code)bcp[1]; + _is_wide = true; + } } } _code = code; diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index 1060a0797a7..396c87f958b 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -54,13 +54,19 @@ Bytecodes::Code Bytecodes::non_breakpoint_code_at(address bcp, methodOop method) return method->orig_bytecode_at(method->bci_from(bcp)); } -int Bytecodes::special_length_at(address bcp) { +int Bytecodes::special_length_at(address bcp, address end) { Code code = code_at(bcp); switch (code) { case _wide: + if (end != NULL && bcp + 1 >= end) { + return -1; // don't read past end of code buffer + } return wide_length_for(cast(*(bcp + 1))); case _tableswitch: { address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize); + if (end != NULL && aligned_bcp + 3*jintSize >= end) { + return -1; // don't read past end of code buffer + } jlong lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize); jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*jintSize; @@ -73,6 +79,9 @@ int Bytecodes::special_length_at(address bcp) { case _fast_binaryswitch: // fall through case _fast_linearswitch: { address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize); + if (end != NULL && aligned_bcp + 2*jintSize >= end) { + return -1; // don't read past end of code buffer + } jlong npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize; // only return len if it can be represented as a positive int; @@ -90,14 +99,17 @@ int Bytecodes::special_length_at(address bcp) { // verifier when reading in bytecode to verify. Other mechanisms that // run at runtime (such as generateOopMaps) need to iterate over the code // and don't expect to see breakpoints: they want to see the instruction -// which was replaces so that they can get the correct length and find +// which was replaced so that they can get the correct length and find // the next bytecode. -int Bytecodes::raw_special_length_at(address bcp) { +// +// 'end' indicates the end of the code buffer, which we should not try to read +// past. +int Bytecodes::raw_special_length_at(address bcp, address end) { Code code = code_or_bp_at(bcp); if (code == _breakpoint) { return 1; } else { - return special_length_at(bcp); + return special_length_at(bcp, end); } } diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 16ddc863bd6..f9201d953f5 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -340,8 +340,10 @@ class Bytecodes: AllStatic { const char* wf = wide_format(code); return (wf == NULL) ? 0 : (int)strlen(wf); } - static int special_length_at(address bcp); - static int raw_special_length_at(address bcp); + // if 'end' is provided, it indicates the end of the code buffer which + // should not be read past when parsing. + static int special_length_at(address bcp, address end = NULL); + static int raw_special_length_at(address bcp, address end = NULL); static int length_at (address bcp) { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); } static int java_length_at (address bcp) { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); } static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; } diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index e74eca8d12c..1de186518d9 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -57,6 +57,14 @@ void Block_List::insert(uint i, Block *b) { _blocks[i] = b; } +#ifndef PRODUCT +void Block_List::print() { + for (uint i=0; i < size(); i++) { + tty->print("B%d ", _blocks[i]->_pre_order); + } + tty->print("size = %d\n", size()); +} +#endif //============================================================================= @@ -66,6 +74,12 @@ uint Block::code_alignment() { // Check for Start block if( _pre_order == 1 ) return InteriorEntryAlignment; // Check for loop alignment + if (has_loop_alignment()) return loop_alignment(); + + return 1; // no particular alignment +} + +uint Block::compute_loop_alignment() { Node *h = head(); if( h->is_Loop() && h->as_Loop()->is_inner_loop() ) { // Pre- and post-loops have low trip count so do not bother with @@ -83,13 +97,15 @@ uint Block::code_alignment() { } return OptoLoopAlignment; // Otherwise align loop head } + return 1; // no particular alignment } //----------------------------------------------------------------------------- // Compute the size of first 'inst_cnt' instructions in this block. // Return the number of instructions left to compute if the block has -// less then 'inst_cnt' instructions. +// less then 'inst_cnt' instructions. Stop, and return 0 if sum_size +// exceeds OptoLoopAlignment. uint Block::compute_first_inst_size(uint& sum_size, uint inst_cnt, PhaseRegAlloc* ra) { uint last_inst = _nodes.size(); @@ -307,6 +323,8 @@ void Block::dump_head( const Block_Array *bbs ) const { tty->print("\tLoop: B%d-B%d ", bhead->_pre_order, bx->_pre_order); // Dump any loop-specific bits, especially for CountedLoops. loop->dump_spec(tty); + } else if (has_loop_alignment()) { + tty->print(" top-of-loop"); } tty->print(" Freq: %g",_freq); if( Verbose || WizardMode ) { @@ -509,9 +527,11 @@ static bool no_flip_branch( Block *b ) { int branch_idx = b->_nodes.size() - b->_num_succs-1; if( branch_idx < 1 ) return false; Node *bra = b->_nodes[branch_idx]; - if( bra->is_Catch() ) return true; + if( bra->is_Catch() ) + return true; if( bra->is_Mach() ) { - if( bra->is_MachNullCheck() ) return true; + if( bra->is_MachNullCheck() ) + return true; int iop = bra->as_Mach()->ideal_Opcode(); if( iop == Op_FastLock || iop == Op_FastUnlock ) return true; @@ -557,10 +577,10 @@ void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) { dead->_nodes[k]->del_req(j); } -//------------------------------MoveToNext------------------------------------- +//------------------------------move_to_next----------------------------------- // Helper function to move block bx to the slot following b_index. Return // true if the move is successful, otherwise false -bool PhaseCFG::MoveToNext(Block* bx, uint b_index) { +bool PhaseCFG::move_to_next(Block* bx, uint b_index) { if (bx == NULL) return false; // Return false if bx is already scheduled. @@ -591,9 +611,9 @@ bool PhaseCFG::MoveToNext(Block* bx, uint b_index) { return true; } -//------------------------------MoveToEnd-------------------------------------- +//------------------------------move_to_end------------------------------------ // Move empty and uncommon blocks to the end. -void PhaseCFG::MoveToEnd(Block *b, uint i) { +void PhaseCFG::move_to_end(Block *b, uint i) { int e = b->is_Empty(); if (e != Block::not_empty) { if (e == Block::empty_with_goto) { @@ -609,15 +629,31 @@ void PhaseCFG::MoveToEnd(Block *b, uint i) { _blocks.push(b); } -//------------------------------RemoveEmpty------------------------------------ -// Remove empty basic blocks and useless branches. -void PhaseCFG::RemoveEmpty() { +//---------------------------set_loop_alignment-------------------------------- +// Set loop alignment for every block +void PhaseCFG::set_loop_alignment() { + uint last = _num_blocks; + assert( _blocks[0] == _broot, "" ); + + for (uint i = 1; i < last; i++ ) { + Block *b = _blocks[i]; + if (b->head()->is_Loop()) { + b->set_loop_alignment(b); + } + } +} + +//-----------------------------remove_empty------------------------------------ +// Make empty basic blocks to be "connector" blocks, Move uncommon blocks +// to the end. +void PhaseCFG::remove_empty() { // Move uncommon blocks to the end uint last = _num_blocks; - uint i; assert( _blocks[0] == _broot, "" ); - for( i = 1; i < last; i++ ) { + + for (uint i = 1; i < last; i++) { Block *b = _blocks[i]; + if (b->is_connector()) break; // Check for NeverBranch at block end. This needs to become a GOTO to the // true target. NeverBranch are treated as a conditional branch that @@ -629,37 +665,40 @@ void PhaseCFG::RemoveEmpty() { convert_NeverBranch_to_Goto(b); // Look for uncommon blocks and move to end. - if( b->is_uncommon(_bbs) ) { - MoveToEnd(b, i); - last--; // No longer check for being uncommon! - if( no_flip_branch(b) ) { // Fall-thru case must follow? - b = _blocks[i]; // Find the fall-thru block - MoveToEnd(b, i); - last--; + if (!C->do_freq_based_layout()) { + if( b->is_uncommon(_bbs) ) { + move_to_end(b, i); + last--; // No longer check for being uncommon! + if( no_flip_branch(b) ) { // Fall-thru case must follow? + b = _blocks[i]; // Find the fall-thru block + move_to_end(b, i); + last--; + } + i--; // backup block counter post-increment } - i--; // backup block counter post-increment } } - // Remove empty blocks - uint j1; + // Move empty blocks to the end last = _num_blocks; - for( i=0; i < last; i++ ) { + for (uint i = 1; i < last; i++) { Block *b = _blocks[i]; - if (i > 0) { - if (b->is_Empty() != Block::not_empty) { - MoveToEnd(b, i); - last--; - i--; - } + if (b->is_Empty() != Block::not_empty) { + move_to_end(b, i); + last--; + i--; } } // End of for all blocks +} +//-----------------------------fixup_flow-------------------------------------- +// Fix up the final control flow for basic blocks. +void PhaseCFG::fixup_flow() { // Fixup final control flow for the blocks. Remove jump-to-next // block. If neither arm of a IF follows the conditional branch, we // have to add a second jump after the conditional. We place the // TRUE branch target in succs[0] for both GOTOs and IFs. - for( i=0; i < _num_blocks; i++ ) { + for (uint i=0; i < _num_blocks; i++) { Block *b = _blocks[i]; b->_pre_order = i; // turn pre-order into block-index @@ -700,7 +739,7 @@ void PhaseCFG::RemoveEmpty() { } } // Remove all CatchProjs - for (j1 = 0; j1 < b->_num_succs; j1++) b->_nodes.pop(); + for (uint j1 = 0; j1 < b->_num_succs; j1++) b->_nodes.pop(); } else if (b->_num_succs == 1) { // Block ends in a Goto? @@ -730,8 +769,7 @@ void PhaseCFG::RemoveEmpty() { // successors after the current one, provided that the // successor was previously unscheduled, but moveable // (i.e., all paths to it involve a branch). - if( bnext != bs0 && bnext != bs1 ) { - + if( !C->do_freq_based_layout() && bnext != bs0 && bnext != bs1 ) { // Choose the more common successor based on the probability // of the conditional branch. Block *bx = bs0; @@ -751,9 +789,9 @@ void PhaseCFG::RemoveEmpty() { } // Attempt the more common successor first - if (MoveToNext(bx, i)) { + if (move_to_next(bx, i)) { bnext = bx; - } else if (MoveToNext(by, i)) { + } else if (move_to_next(by, i)) { bnext = by; } } @@ -774,10 +812,8 @@ void PhaseCFG::RemoveEmpty() { // Flip projection for each target { ProjNode *tmp = proj0; proj0 = proj1; proj1 = tmp; } - } else if( bnext == bs1 ) { // Fall-thru is already in succs[1] - - } else { // Else need a double-branch - + } else if( bnext != bs1 ) { + // Need a double-branch // The existing conditional branch need not change. // Add a unconditional branch to the false target. // Alas, it must appear in its own block and adding a @@ -786,8 +822,9 @@ void PhaseCFG::RemoveEmpty() { } // Make sure we TRUE branch to the target - if( proj0->Opcode() == Op_IfFalse ) + if( proj0->Opcode() == Op_IfFalse ) { iff->negate(); + } b->_nodes.pop(); // Remove IfFalse & IfTrue projections b->_nodes.pop(); @@ -796,9 +833,7 @@ void PhaseCFG::RemoveEmpty() { // Multi-exit block, e.g. a switch statement // But we don't need to do anything here } - } // End of for all blocks - } @@ -905,7 +940,7 @@ void UnionFind::reset( uint max ) { // Force the Union-Find mapping to be at least this large extend(max,0); // Initialize to be the ID mapping. - for( uint i=0; i<_max; i++ ) map(i,i); + for( uint i=0; i= _max ) return idx; uint next = lookup(idx); while( next != idx ) { // Scan chain of equivalences - assert( next < idx, "always union smaller" ); idx = next; // until find a fixed-point next = lookup(idx); } @@ -956,3 +990,491 @@ void UnionFind::Union( uint idx1, uint idx2 ) { assert( src < dst, "always union smaller" ); map(dst,src); } + +#ifndef PRODUCT +static void edge_dump(GrowableArray *edges) { + tty->print_cr("---- Edges ----"); + for (int i = 0; i < edges->length(); i++) { + CFGEdge *e = edges->at(i); + if (e != NULL) { + edges->at(i)->dump(); + } + } +} + +static void trace_dump(Trace *traces[], int count) { + tty->print_cr("---- Traces ----"); + for (int i = 0; i < count; i++) { + Trace *tr = traces[i]; + if (tr != NULL) { + tr->dump(); + } + } +} + +void Trace::dump( ) const { + tty->print_cr("Trace (freq %f)", first_block()->_freq); + for (Block *b = first_block(); b != NULL; b = next(b)) { + tty->print(" B%d", b->_pre_order); + if (b->head()->is_Loop()) { + tty->print(" (L%d)", b->compute_loop_alignment()); + } + if (b->has_loop_alignment()) { + tty->print(" (T%d)", b->code_alignment()); + } + } + tty->cr(); +} + +void CFGEdge::dump( ) const { + tty->print(" B%d --> B%d Freq: %f out:%3d%% in:%3d%% State: ", + from()->_pre_order, to()->_pre_order, freq(), _from_pct, _to_pct); + switch(state()) { + case connected: + tty->print("connected"); + break; + case open: + tty->print("open"); + break; + case interior: + tty->print("interior"); + break; + } + if (infrequent()) { + tty->print(" infrequent"); + } + tty->cr(); +} +#endif + +//============================================================================= + +//------------------------------edge_order------------------------------------- +// Comparison function for edges +static int edge_order(CFGEdge **e0, CFGEdge **e1) { + float freq0 = (*e0)->freq(); + float freq1 = (*e1)->freq(); + if (freq0 != freq1) { + return freq0 > freq1 ? -1 : 1; + } + + int dist0 = (*e0)->to()->_rpo - (*e0)->from()->_rpo; + int dist1 = (*e1)->to()->_rpo - (*e1)->from()->_rpo; + + return dist1 - dist0; +} + +//------------------------------trace_frequency_order-------------------------- +// Comparison function for edges +static int trace_frequency_order(const void *p0, const void *p1) { + Trace *tr0 = *(Trace **) p0; + Trace *tr1 = *(Trace **) p1; + Block *b0 = tr0->first_block(); + Block *b1 = tr1->first_block(); + + // The trace of connector blocks goes at the end; + // we only expect one such trace + if (b0->is_connector() != b1->is_connector()) { + return b1->is_connector() ? -1 : 1; + } + + // Pull more frequently executed blocks to the beginning + float freq0 = b0->_freq; + float freq1 = b1->_freq; + if (freq0 != freq1) { + return freq0 > freq1 ? -1 : 1; + } + + int diff = tr0->first_block()->_rpo - tr1->first_block()->_rpo; + + return diff; +} + +//------------------------------find_edges------------------------------------- +// Find edges of interest, i.e, those which can fall through. Presumes that +// edges which don't fall through are of low frequency and can be generally +// ignored. Initialize the list of traces. +void PhaseBlockLayout::find_edges() +{ + // Walk the blocks, creating edges and Traces + uint i; + Trace *tr = NULL; + for (i = 0; i < _cfg._num_blocks; i++) { + Block *b = _cfg._blocks[i]; + tr = new Trace(b, next, prev); + traces[tr->id()] = tr; + + // All connector blocks should be at the end of the list + if (b->is_connector()) break; + + // If this block and the next one have a one-to-one successor + // predecessor relationship, simply append the next block + int nfallthru = b->num_fall_throughs(); + while (nfallthru == 1 && + b->succ_fall_through(0)) { + Block *n = b->_succs[0]; + + // Skip over single-entry connector blocks, we don't want to + // add them to the trace. + while (n->is_connector() && n->num_preds() == 1) { + n = n->_succs[0]; + } + + // We see a merge point, so stop search for the next block + if (n->num_preds() != 1) break; + + i++; + assert(n = _cfg._blocks[i], "expecting next block"); + tr->append(n); + uf->map(n->_pre_order, tr->id()); + traces[n->_pre_order] = NULL; + nfallthru = b->num_fall_throughs(); + b = n; + } + + if (nfallthru > 0) { + // Create a CFGEdge for each outgoing + // edge that could be a fall-through. + for (uint j = 0; j < b->_num_succs; j++ ) { + if (b->succ_fall_through(j)) { + Block *target = b->non_connector_successor(j); + float freq = b->_freq * b->succ_prob(j); + int from_pct = (int) ((100 * freq) / b->_freq); + int to_pct = (int) ((100 * freq) / target->_freq); + edges->append(new CFGEdge(b, target, freq, from_pct, to_pct)); + } + } + } + } + + // Group connector blocks into one trace + for (i++; i < _cfg._num_blocks; i++) { + Block *b = _cfg._blocks[i]; + assert(b->is_connector(), "connector blocks at the end"); + tr->append(b); + uf->map(b->_pre_order, tr->id()); + traces[b->_pre_order] = NULL; + } +} + +//------------------------------union_traces---------------------------------- +// Union two traces together in uf, and null out the trace in the list +void PhaseBlockLayout::union_traces(Trace* updated_trace, Trace* old_trace) +{ + uint old_id = old_trace->id(); + uint updated_id = updated_trace->id(); + + uint lo_id = updated_id; + uint hi_id = old_id; + + // If from is greater than to, swap values to meet + // UnionFind guarantee. + if (updated_id > old_id) { + lo_id = old_id; + hi_id = updated_id; + + // Fix up the trace ids + traces[lo_id] = traces[updated_id]; + updated_trace->set_id(lo_id); + } + + // Union the lower with the higher and remove the pointer + // to the higher. + uf->Union(lo_id, hi_id); + traces[hi_id] = NULL; +} + +//------------------------------grow_traces------------------------------------- +// Append traces together via the most frequently executed edges +void PhaseBlockLayout::grow_traces() +{ + // Order the edges, and drive the growth of Traces via the most + // frequently executed edges. + edges->sort(edge_order); + for (int i = 0; i < edges->length(); i++) { + CFGEdge *e = edges->at(i); + + if (e->state() != CFGEdge::open) continue; + + Block *src_block = e->from(); + Block *targ_block = e->to(); + + // Don't grow traces along backedges? + if (!BlockLayoutRotateLoops) { + if (targ_block->_rpo <= src_block->_rpo) { + targ_block->set_loop_alignment(targ_block); + continue; + } + } + + Trace *src_trace = trace(src_block); + Trace *targ_trace = trace(targ_block); + + // If the edge in question can join two traces at their ends, + // append one trace to the other. + if (src_trace->last_block() == src_block) { + if (src_trace == targ_trace) { + e->set_state(CFGEdge::interior); + if (targ_trace->backedge(e)) { + // Reset i to catch any newly eligible edge + // (Or we could remember the first "open" edge, and reset there) + i = 0; + } + } else if (targ_trace->first_block() == targ_block) { + e->set_state(CFGEdge::connected); + src_trace->append(targ_trace); + union_traces(src_trace, targ_trace); + } + } + } +} + +//------------------------------merge_traces----------------------------------- +// Embed one trace into another, if the fork or join points are sufficiently +// balanced. +void PhaseBlockLayout::merge_traces(bool fall_thru_only) +{ + // Walk the edge list a another time, looking at unprocessed edges. + // Fold in diamonds + for (int i = 0; i < edges->length(); i++) { + CFGEdge *e = edges->at(i); + + if (e->state() != CFGEdge::open) continue; + if (fall_thru_only) { + if (e->infrequent()) continue; + } + + Block *src_block = e->from(); + Trace *src_trace = trace(src_block); + bool src_at_tail = src_trace->last_block() == src_block; + + Block *targ_block = e->to(); + Trace *targ_trace = trace(targ_block); + bool targ_at_start = targ_trace->first_block() == targ_block; + + if (src_trace == targ_trace) { + // This may be a loop, but we can't do much about it. + e->set_state(CFGEdge::interior); + continue; + } + + if (fall_thru_only) { + // If the edge links the middle of two traces, we can't do anything. + // Mark the edge and continue. + if (!src_at_tail & !targ_at_start) { + continue; + } + + // Don't grow traces along backedges? + if (!BlockLayoutRotateLoops && (targ_block->_rpo <= src_block->_rpo)) { + continue; + } + + // If both ends of the edge are available, why didn't we handle it earlier? + assert(src_at_tail ^ targ_at_start, "Should have caught this edge earlier."); + + if (targ_at_start) { + // Insert the "targ" trace in the "src" trace if the insertion point + // is a two way branch. + // Better profitability check possible, but may not be worth it. + // Someday, see if the this "fork" has an associated "join"; + // then make a policy on merging this trace at the fork or join. + // For example, other things being equal, it may be better to place this + // trace at the join point if the "src" trace ends in a two-way, but + // the insertion point is one-way. + assert(src_block->num_fall_throughs() == 2, "unexpected diamond"); + e->set_state(CFGEdge::connected); + src_trace->insert_after(src_block, targ_trace); + union_traces(src_trace, targ_trace); + } else if (src_at_tail) { + if (src_trace != trace(_cfg._broot)) { + e->set_state(CFGEdge::connected); + targ_trace->insert_before(targ_block, src_trace); + union_traces(targ_trace, src_trace); + } + } + } else if (e->state() == CFGEdge::open) { + // Append traces, even without a fall-thru connection. + // But leave root entry at the begining of the block list. + if (targ_trace != trace(_cfg._broot)) { + e->set_state(CFGEdge::connected); + src_trace->append(targ_trace); + union_traces(src_trace, targ_trace); + } + } + } +} + +//----------------------------reorder_traces----------------------------------- +// Order the sequence of the traces in some desirable way, and fixup the +// jumps at the end of each block. +void PhaseBlockLayout::reorder_traces(int count) +{ + ResourceArea *area = Thread::current()->resource_area(); + Trace ** new_traces = NEW_ARENA_ARRAY(area, Trace *, count); + Block_List worklist; + int new_count = 0; + + // Compact the traces. + for (int i = 0; i < count; i++) { + Trace *tr = traces[i]; + if (tr != NULL) { + new_traces[new_count++] = tr; + } + } + + // The entry block should be first on the new trace list. + Trace *tr = trace(_cfg._broot); + assert(tr == new_traces[0], "entry trace misplaced"); + + // Sort the new trace list by frequency + qsort(new_traces + 1, new_count - 1, sizeof(new_traces[0]), trace_frequency_order); + + // Patch up the successor blocks + _cfg._blocks.reset(); + _cfg._num_blocks = 0; + for (int i = 0; i < new_count; i++) { + Trace *tr = new_traces[i]; + if (tr != NULL) { + tr->fixup_blocks(_cfg); + } + } +} + +//------------------------------PhaseBlockLayout------------------------------- +// Order basic blocks based on frequency +PhaseBlockLayout::PhaseBlockLayout(PhaseCFG &cfg) : + Phase(BlockLayout), + _cfg(cfg) +{ + ResourceMark rm; + ResourceArea *area = Thread::current()->resource_area(); + + // List of traces + int size = _cfg._num_blocks + 1; + traces = NEW_ARENA_ARRAY(area, Trace *, size); + memset(traces, 0, size*sizeof(Trace*)); + next = NEW_ARENA_ARRAY(area, Block *, size); + memset(next, 0, size*sizeof(Block *)); + prev = NEW_ARENA_ARRAY(area, Block *, size); + memset(prev , 0, size*sizeof(Block *)); + + // List of edges + edges = new GrowableArray; + + // Mapping block index --> block_trace + uf = new UnionFind(size); + uf->reset(size); + + // Find edges and create traces. + find_edges(); + + // Grow traces at their ends via most frequent edges. + grow_traces(); + + // Merge one trace into another, but only at fall-through points. + // This may make diamonds and other related shapes in a trace. + merge_traces(true); + + // Run merge again, allowing two traces to be catenated, even if + // one does not fall through into the other. This appends loosely + // related traces to be near each other. + merge_traces(false); + + // Re-order all the remaining traces by frequency + reorder_traces(size); + + assert(_cfg._num_blocks >= (uint) (size - 1), "number of blocks can not shrink"); +} + + +//------------------------------backedge--------------------------------------- +// Edge e completes a loop in a trace. If the target block is head of the +// loop, rotate the loop block so that the loop ends in a conditional branch. +bool Trace::backedge(CFGEdge *e) { + bool loop_rotated = false; + Block *src_block = e->from(); + Block *targ_block = e->to(); + + assert(last_block() == src_block, "loop discovery at back branch"); + if (first_block() == targ_block) { + if (BlockLayoutRotateLoops && last_block()->num_fall_throughs() < 2) { + // Find the last block in the trace that has a conditional + // branch. + Block *b; + for (b = last_block(); b != NULL; b = prev(b)) { + if (b->num_fall_throughs() == 2) { + break; + } + } + + if (b != last_block() && b != NULL) { + loop_rotated = true; + + // Rotate the loop by doing two-part linked-list surgery. + append(first_block()); + break_loop_after(b); + } + } + + // Backbranch to the top of a trace + // Scroll foward through the trace from the targ_block. If we find + // a loop head before another loop top, use the the loop head alignment. + for (Block *b = targ_block; b != NULL; b = next(b)) { + if (b->has_loop_alignment()) { + break; + } + if (b->head()->is_Loop()) { + targ_block = b; + break; + } + } + + first_block()->set_loop_alignment(targ_block); + + } else { + // Backbranch into the middle of a trace + targ_block->set_loop_alignment(targ_block); + } + + return loop_rotated; +} + +//------------------------------fixup_blocks----------------------------------- +// push blocks onto the CFG list +// ensure that blocks have the correct two-way branch sense +void Trace::fixup_blocks(PhaseCFG &cfg) { + Block *last = last_block(); + for (Block *b = first_block(); b != NULL; b = next(b)) { + cfg._blocks.push(b); + cfg._num_blocks++; + if (!b->is_connector()) { + int nfallthru = b->num_fall_throughs(); + if (b != last) { + if (nfallthru == 2) { + // Ensure that the sense of the branch is correct + Block *bnext = next(b); + Block *bs0 = b->non_connector_successor(0); + + MachNode *iff = b->_nodes[b->_nodes.size()-3]->as_Mach(); + ProjNode *proj0 = b->_nodes[b->_nodes.size()-2]->as_Proj(); + ProjNode *proj1 = b->_nodes[b->_nodes.size()-1]->as_Proj(); + + if (bnext == bs0) { + // Fall-thru case in succs[0], should be in succs[1] + + // Flip targets in _succs map + Block *tbs0 = b->_succs[0]; + Block *tbs1 = b->_succs[1]; + b->_succs.map( 0, tbs1 ); + b->_succs.map( 1, tbs0 ); + + // Flip projections to match targets + b->_nodes.map(b->_nodes.size()-2, proj1); + b->_nodes.map(b->_nodes.size()-1, proj0); + } + } + } + } + } +} diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index 8708a4dedf8..52163809568 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -75,6 +75,7 @@ public: void insert( uint i, Block *n ); uint size() const { return _cnt; } void reset() { _cnt = 0; } + void print(); }; @@ -129,7 +130,11 @@ class Block : public CFGElement { uint _rpo; // Number in reverse post order walk virtual bool is_block() { return true; } - float succ_prob(uint i); // return probability of i'th successor + float succ_prob(uint i); // return probability of i'th successor + int num_fall_throughs(); // How many fall-through candidate this block has + void update_uncommon_branch(Block* un); // Lower branch prob to uncommon code + bool succ_fall_through(uint i); // Is successor "i" is a fall-through candidate + Block* lone_fall_through(); // Return lone fall-through Block or null Block* dom_lca(Block* that); // Compute LCA in dominator tree. #ifdef ASSERT @@ -144,6 +149,7 @@ class Block : public CFGElement { // Report the alignment required by this block. Must be a power of 2. // The previous block will insert nops to get this alignment. uint code_alignment(); + uint compute_loop_alignment(); // BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies. // It is currently also used to scale such frequencies relative to @@ -184,11 +190,12 @@ class Block : public CFGElement { int current_alignment = current_offset & max_pad; if( current_alignment != 0 ) { uint padding = (block_alignment-current_alignment) & max_pad; - if( !head()->is_Loop() || - padding <= (uint)MaxLoopPad || - first_inst_size() > padding ) { - return padding; + if( has_loop_alignment() && + padding > (uint)MaxLoopPad && + first_inst_size() <= padding ) { + return 0; } + return padding; } } return 0; @@ -202,6 +209,21 @@ class Block : public CFGElement { void set_connector() { _connector = true; } bool is_connector() const { return _connector; }; + // Loop_alignment will be set for blocks which are at the top of loops. + // The block layout pass may rotate loops such that the loop head may not + // be the sequentially first block of the loop encountered in the linear + // list of blocks. If the layout pass is not run, loop alignment is set + // for each block which is the head of a loop. + uint _loop_alignment; + void set_loop_alignment(Block *loop_top) { + uint new_alignment = loop_top->compute_loop_alignment(); + if (new_alignment > _loop_alignment) { + _loop_alignment = new_alignment; + } + } + uint loop_alignment() const { return _loop_alignment; } + bool has_loop_alignment() const { return loop_alignment() > 0; } + // Create a new Block with given head Node. // Creates the (empty) predecessor arrays. Block( Arena *a, Node *headnode ) @@ -219,7 +241,8 @@ class Block : public CFGElement { _raise_LCA_mark(0), _raise_LCA_visited(0), _first_inst_size(999999), - _connector(false) { + _connector(false), + _loop_alignment(0) { _nodes.push(headnode); } @@ -275,6 +298,16 @@ class Block : public CFGElement { return s; } + // Return true if b is a successor of this block + bool has_successor(Block* b) const { + for (uint i = 0; i < _num_succs; i++ ) { + if (non_connector_successor(i) == b) { + return true; + } + } + return false; + } + // Successor block, after forwarding through connectors Block* non_connector_successor(int i) const { return _succs[i]->non_connector(); @@ -319,7 +352,6 @@ class PhaseCFG : public Phase { // I'll need a few machine-specific GotoNodes. Clone from this one. MachNode *_goto; - void insert_goto_at(uint block_no, uint succ_no); Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false); void verify_anti_dependences(Block* LCA, Node* load) { @@ -379,10 +411,15 @@ class PhaseCFG : public Phase { // Compute the instruction global latency with a backwards walk void ComputeLatenciesBackwards(VectorSet &visited, Node_List &stack); + // Set loop alignment + void set_loop_alignment(); + // Remove empty basic blocks - void RemoveEmpty(); - bool MoveToNext(Block* bx, uint b_index); - void MoveToEnd(Block* bx, uint b_index); + void remove_empty(); + void fixup_flow(); + bool move_to_next(Block* bx, uint b_index); + void move_to_end(Block* bx, uint b_index); + void insert_goto_at(uint block_no, uint succ_no); // Check for NeverBranch at block end. This needs to become a GOTO to the // true target. NeverBranch are treated as a conditional branch that always @@ -413,7 +450,7 @@ class PhaseCFG : public Phase { }; -//------------------------------UnionFindInfo---------------------------------- +//------------------------------UnionFind-------------------------------------- // Map Block indices to a block-index for a cfg-cover. // Array lookup in the optimized case. class UnionFind : public ResourceObj { @@ -508,3 +545,166 @@ class CFGLoop : public CFGElement { void dump_tree() const; #endif }; + + +//----------------------------------CFGEdge------------------------------------ +// A edge between two basic blocks that will be embodied by a branch or a +// fall-through. +class CFGEdge : public ResourceObj { + private: + Block * _from; // Source basic block + Block * _to; // Destination basic block + float _freq; // Execution frequency (estimate) + int _state; + bool _infrequent; + int _from_pct; + int _to_pct; + + // Private accessors + int from_pct() const { return _from_pct; } + int to_pct() const { return _to_pct; } + int from_infrequent() const { return from_pct() < BlockLayoutMinDiamondPercentage; } + int to_infrequent() const { return to_pct() < BlockLayoutMinDiamondPercentage; } + + public: + enum { + open, // initial edge state; unprocessed + connected, // edge used to connect two traces together + interior // edge is interior to trace (could be backedge) + }; + + CFGEdge(Block *from, Block *to, float freq, int from_pct, int to_pct) : + _from(from), _to(to), _freq(freq), + _from_pct(from_pct), _to_pct(to_pct), _state(open) { + _infrequent = from_infrequent() || to_infrequent(); + } + + float freq() const { return _freq; } + Block* from() const { return _from; } + Block* to () const { return _to; } + int infrequent() const { return _infrequent; } + int state() const { return _state; } + + void set_state(int state) { _state = state; } + +#ifndef PRODUCT + void dump( ) const; +#endif +}; + + +//-----------------------------------Trace------------------------------------- +// An ordered list of basic blocks. +class Trace : public ResourceObj { + private: + uint _id; // Unique Trace id (derived from initial block) + Block ** _next_list; // Array mapping index to next block + Block ** _prev_list; // Array mapping index to previous block + Block * _first; // First block in the trace + Block * _last; // Last block in the trace + + // Return the block that follows "b" in the trace. + Block * next(Block *b) const { return _next_list[b->_pre_order]; } + void set_next(Block *b, Block *n) const { _next_list[b->_pre_order] = n; } + + // Return the block that preceeds "b" in the trace. + Block * prev(Block *b) const { return _prev_list[b->_pre_order]; } + void set_prev(Block *b, Block *p) const { _prev_list[b->_pre_order] = p; } + + // We've discovered a loop in this trace. Reset last to be "b", and first as + // the block following "b + void break_loop_after(Block *b) { + _last = b; + _first = next(b); + set_prev(_first, NULL); + set_next(_last, NULL); + } + + public: + + Trace(Block *b, Block **next_list, Block **prev_list) : + _first(b), + _last(b), + _next_list(next_list), + _prev_list(prev_list), + _id(b->_pre_order) { + set_next(b, NULL); + set_prev(b, NULL); + }; + + // Return the id number + uint id() const { return _id; } + void set_id(uint id) { _id = id; } + + // Return the first block in the trace + Block * first_block() const { return _first; } + + // Return the last block in the trace + Block * last_block() const { return _last; } + + // Insert a trace in the middle of this one after b + void insert_after(Block *b, Trace *tr) { + set_next(tr->last_block(), next(b)); + if (next(b) != NULL) { + set_prev(next(b), tr->last_block()); + } + + set_next(b, tr->first_block()); + set_prev(tr->first_block(), b); + + if (b == _last) { + _last = tr->last_block(); + } + } + + void insert_before(Block *b, Trace *tr) { + Block *p = prev(b); + assert(p != NULL, "use append instead"); + insert_after(p, tr); + } + + // Append another trace to this one. + void append(Trace *tr) { + insert_after(_last, tr); + } + + // Append a block at the end of this trace + void append(Block *b) { + set_next(_last, b); + set_prev(b, _last); + _last = b; + } + + // Adjust the the blocks in this trace + void fixup_blocks(PhaseCFG &cfg); + bool backedge(CFGEdge *e); + +#ifndef PRODUCT + void dump( ) const; +#endif +}; + +//------------------------------PhaseBlockLayout------------------------------- +// Rearrange blocks into some canonical order, based on edges and their frequencies +class PhaseBlockLayout : public Phase { + PhaseCFG &_cfg; // Control flow graph + + GrowableArray *edges; + Trace **traces; + Block **next; + Block **prev; + UnionFind *uf; + + // Given a block, find its encompassing Trace + Trace * trace(Block *b) { + return traces[uf->Find_compress(b->_pre_order)]; + } + public: + PhaseBlockLayout(PhaseCFG &cfg); + + void find_edges(); + void grow_traces(); + void merge_traces(bool loose_connections); + void reorder_traces(int count); + void union_traces(Trace* from, Trace* to); +}; diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index affd56a86e2..1342091350c 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -388,6 +388,9 @@ product(intx, EliminateAllocationArraySizeLimit, 64, \ "Array size (number of elements) limit for scalar replacement") \ \ + product(bool, UseOptoBiasInlining, true, \ + "Generate biased locking code in C2 ideal graph") \ + \ product(intx, ValueSearchLimit, 1000, \ "Recursion limit in PhaseMacroExpand::value_from_mem_phi") \ \ @@ -396,5 +399,15 @@ \ diagnostic(intx, DominatorSearchLimit, 1000, \ "Iterations limit in Node::dominates") \ + \ + product(bool, BlockLayoutByFrequency, true, \ + "Use edge frequencies to drive block ordering") \ + \ + product(intx, BlockLayoutMinDiamondPercentage, 20, \ + "Miniumum %% of a successor (predecessor) for which block layout "\ + "a will allow a fork (join) in a single chain") \ + \ + product(bool, BlockLayoutRotateLoops, false, \ + "Allow back branches to be fall throughs in the block layour") \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 8e8fc24da20..b9e9cbd5587 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -967,6 +967,7 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp, init_class_id(Class_SafePointScalarObject); } +bool SafePointScalarObjectNode::pinned() const { return true; } uint SafePointScalarObjectNode::ideal_reg() const { return 0; // No matching to machine instruction diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index 20192ddf0f6..45b6dd2148b 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -433,6 +433,10 @@ public: uint n_fields() const { return _n_fields; } DEBUG_ONLY(AllocateNode* alloc() const { return _alloc; }) + // SafePointScalarObject should be always pinned to the control edge + // of the SafePoint node for which it was generated. + virtual bool pinned() const; // { return true; } + virtual uint size_of() const { return sizeof(*this); } // Assumes that "this" is an argument to a safepoint node "s", and that diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index 74a0fce9014..0456db5dc11 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -440,9 +440,7 @@ void PhaseChaitin::Register_Allocate() { assert((int)(_matcher._new_SP+_framesize) >= (int)_matcher._out_arg_limit, "framesize must be large enough"); // This frame must preserve the required fp alignment - const int stack_alignment_in_words = Matcher::stack_alignment_in_slots(); - if (stack_alignment_in_words > 0) - _framesize = round_to(_framesize, Matcher::stack_alignment_in_bytes()); + _framesize = round_to(_framesize, Matcher::stack_alignment_in_slots()); assert( _framesize >= 0 && _framesize <= 1000000, "sanity check" ); #ifndef PRODUCT _total_framesize += _framesize; diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 0371736cf10..14b43120059 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -205,6 +205,7 @@ macro(StoreB) macro(StoreC) macro(StoreCM) macro(StorePConditional) +macro(StoreIConditional) macro(StoreLConditional) macro(StoreD) macro(StoreF) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 91ae2e6b8f5..42eae3063d9 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -551,7 +551,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr rethrow_exceptions(kit.transfer_exceptions_into_jvms()); } - print_method("Before RemoveUseless"); + print_method("Before RemoveUseless", 3); // Remove clutter produced by parsing. if (!failing()) { @@ -822,6 +822,7 @@ void Compile::Init(int aliaslevel) { Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist)); set_decompile_count(0); + set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency")); // Compilation level related initialization if (env()->comp_level() == CompLevel_fast_compile) { set_num_loop_opts(Tier1LoopOptsCount); @@ -1701,8 +1702,14 @@ void Compile::Code_Gen() { // are not adding any new instructions. If any basic block is empty, we // can now safely remove it. { - NOT_PRODUCT( TracePhase t2("removeEmpty", &_t_removeEmptyBlocks, TimeCompiler); ) - cfg.RemoveEmpty(); + NOT_PRODUCT( TracePhase t2("blockOrdering", &_t_blockOrdering, TimeCompiler); ) + cfg.remove_empty(); + if (do_freq_based_layout()) { + PhaseBlockLayout layout(cfg); + } else { + cfg.set_loop_alignment(); + } + cfg.fixup_flow(); } // Perform any platform dependent postallocation verifications. @@ -1994,6 +2001,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { case Op_StorePConditional: case Op_StoreI: case Op_StoreL: + case Op_StoreIConditional: case Op_StoreLConditional: case Op_CompareAndSwapI: case Op_CompareAndSwapL: diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 3310bb99003..dcd6813a893 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -154,6 +154,7 @@ class Compile : public Phase { uint _decompile_count; // Cumulative decompilation counts. bool _do_inlining; // True if we intend to do inlining bool _do_scheduling; // True if we intend to do scheduling + bool _do_freq_based_layout; // True if we intend to do frequency based block layout bool _do_count_invocations; // True if we generate code to count invocations bool _do_method_data_update; // True if we generate code to update methodDataOops int _AliasLevel; // Locally-adjusted version of AliasLevel flag. @@ -307,6 +308,8 @@ class Compile : public Phase { void set_do_inlining(bool z) { _do_inlining = z; } bool do_scheduling() const { return _do_scheduling; } void set_do_scheduling(bool z) { _do_scheduling = z; } + bool do_freq_based_layout() const{ return _do_freq_based_layout; } + void set_do_freq_based_layout(bool z){ _do_freq_based_layout = z; } bool do_count_invocations() const{ return _do_count_invocations; } void set_do_count_invocations(bool z){ _do_count_invocations = z; } bool do_method_data_update() const { return _do_method_data_update; } diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index b65101197cb..c3d9db916bc 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1319,11 +1319,33 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_ //------------------------------Estimate_Block_Frequency----------------------- // Estimate block frequencies based on IfNode probabilities. void PhaseCFG::Estimate_Block_Frequency() { - int cnts = C->method() ? C->method()->interpreter_invocation_count() : 1; - // Most of our algorithms will die horribly if frequency can become - // negative so make sure cnts is a sane value. - if( cnts <= 0 ) cnts = 1; - float f = (float)cnts/(float)FreqCountInvocations; + + // Force conditional branches leading to uncommon traps to be unlikely, + // not because we get to the uncommon_trap with less relative frequency, + // but because an uncommon_trap typically causes a deopt, so we only get + // there once. + if (C->do_freq_based_layout()) { + Block_List worklist; + Block* root_blk = _blocks[0]; + for (uint i = 1; i < root_blk->num_preds(); i++) { + Block *pb = _bbs[root_blk->pred(i)->_idx]; + if (pb->has_uncommon_code()) { + worklist.push(pb); + } + } + while (worklist.size() > 0) { + Block* uct = worklist.pop(); + if (uct == _broot) continue; + for (uint i = 1; i < uct->num_preds(); i++) { + Block *pb = _bbs[uct->pred(i)->_idx]; + if (pb->_num_succs == 1) { + worklist.push(pb); + } else if (pb->num_fall_throughs() == 2) { + pb->update_uncommon_branch(uct); + } + } + } + } // Create the loop tree and calculate loop depth. _root_loop = create_loop_tree(); @@ -1333,27 +1355,29 @@ void PhaseCFG::Estimate_Block_Frequency() { _root_loop->compute_freq(); // Adjust all frequencies to be relative to a single method entry - _root_loop->_freq = f * 1.0; + _root_loop->_freq = 1.0; _root_loop->scale_freq(); // force paths ending at uncommon traps to be infrequent - Block_List worklist; - Block* root_blk = _blocks[0]; - for (uint i = 0; i < root_blk->num_preds(); i++) { - Block *pb = _bbs[root_blk->pred(i)->_idx]; - if (pb->has_uncommon_code()) { - worklist.push(pb); - } - } - while (worklist.size() > 0) { - Block* uct = worklist.pop(); - uct->_freq = PROB_MIN; - for (uint i = 0; i < uct->num_preds(); i++) { - Block *pb = _bbs[uct->pred(i)->_idx]; - if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) { + if (!C->do_freq_based_layout()) { + Block_List worklist; + Block* root_blk = _blocks[0]; + for (uint i = 1; i < root_blk->num_preds(); i++) { + Block *pb = _bbs[root_blk->pred(i)->_idx]; + if (pb->has_uncommon_code()) { worklist.push(pb); } } + while (worklist.size() > 0) { + Block* uct = worklist.pop(); + uct->_freq = PROB_MIN; + for (uint i = 1; i < uct->num_preds(); i++) { + Block *pb = _bbs[uct->pred(i)->_idx]; + if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) { + worklist.push(pb); + } + } + } } #ifndef PRODUCT @@ -1556,22 +1580,6 @@ void CFGLoop::compute_freq() { } } -#if 0 - // Raise frequency of the loop backedge block, in an effort - // to keep it empty. Skip the method level "loop". - if (_parent != NULL) { - CFGElement* s = _members.at(_members.length() - 1); - if (s->is_block()) { - Block* bk = s->as_Block(); - if (bk->_num_succs == 1 && bk->_succs[0] == hd) { - // almost any value >= 1.0f works - // FIXME: raw constant - bk->_freq = 1.05f; - } - } - } -#endif - // For all loops other than the outer, "method" loop, // sum and normalize the exit probability. The "method" loop // should keep the initial exit probability of 1, so that @@ -1589,12 +1597,15 @@ void CFGLoop::compute_freq() { // the probability of exit per loop entry. for (int i = 0; i < _exits.length(); i++) { Block* et = _exits.at(i).get_target(); - float new_prob = _exits.at(i).get_prob() / exits_sum; + float new_prob = 0.0f; + if (_exits.at(i).get_prob() > 0.0f) { + new_prob = _exits.at(i).get_prob() / exits_sum; + } BlockProbPair bpp(et, new_prob); _exits.at_put(i, bpp); } - // Save the total, but guard against unreasoable probability, + // Save the total, but guard against unreasonable probability, // as the value is used to estimate the loop trip count. // An infinite trip count would blur relative block // frequencies. @@ -1688,6 +1699,137 @@ float Block::succ_prob(uint i) { return 0.0f; } +//------------------------------num_fall_throughs----------------------------- +// Return the number of fall-through candidates for a block +int Block::num_fall_throughs() { + int eidx = end_idx(); + Node *n = _nodes[eidx]; // Get ending Node + + int op = n->Opcode(); + if (n->is_Mach()) { + if (n->is_MachNullCheck()) { + // In theory, either side can fall-thru, for simplicity sake, + // let's say only the false branch can now. + return 1; + } + op = n->as_Mach()->ideal_Opcode(); + } + + // Switch on branch type + switch( op ) { + case Op_CountedLoopEnd: + case Op_If: + return 2; + + case Op_Root: + case Op_Goto: + return 1; + + case Op_Catch: { + for (uint i = 0; i < _num_succs; i++) { + const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj(); + if (ci->_con == CatchProjNode::fall_through_index) { + return 1; + } + } + return 0; + } + + case Op_Jump: + case Op_NeverBranch: + case Op_TailCall: + case Op_TailJump: + case Op_Return: + case Op_Halt: + case Op_Rethrow: + return 0; + + default: + ShouldNotReachHere(); + } + + return 0; +} + +//------------------------------succ_fall_through----------------------------- +// Return true if a specific successor could be fall-through target. +bool Block::succ_fall_through(uint i) { + int eidx = end_idx(); + Node *n = _nodes[eidx]; // Get ending Node + + int op = n->Opcode(); + if (n->is_Mach()) { + if (n->is_MachNullCheck()) { + // In theory, either side can fall-thru, for simplicity sake, + // let's say only the false branch can now. + return _nodes[i + eidx + 1]->Opcode() == Op_IfFalse; + } + op = n->as_Mach()->ideal_Opcode(); + } + + // Switch on branch type + switch( op ) { + case Op_CountedLoopEnd: + case Op_If: + case Op_Root: + case Op_Goto: + return true; + + case Op_Catch: { + const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj(); + return ci->_con == CatchProjNode::fall_through_index; + } + + case Op_Jump: + case Op_NeverBranch: + case Op_TailCall: + case Op_TailJump: + case Op_Return: + case Op_Halt: + case Op_Rethrow: + return false; + + default: + ShouldNotReachHere(); + } + + return false; +} + +//------------------------------update_uncommon_branch------------------------ +// Update the probability of a two-branch to be uncommon +void Block::update_uncommon_branch(Block* ub) { + int eidx = end_idx(); + Node *n = _nodes[eidx]; // Get ending Node + + int op = n->as_Mach()->ideal_Opcode(); + + assert(op == Op_CountedLoopEnd || op == Op_If, "must be a If"); + assert(num_fall_throughs() == 2, "must be a two way branch block"); + + // Which successor is ub? + uint s; + for (s = 0; s <_num_succs; s++) { + if (_succs[s] == ub) break; + } + assert(s < 2, "uncommon successor must be found"); + + // If ub is the true path, make the proability small, else + // ub is the false path, and make the probability large + bool invert = (_nodes[s + eidx + 1]->Opcode() == Op_IfFalse); + + // Get existing probability + float p = n->as_MachIf()->_prob; + + if (invert) p = 1.0 - p; + if (p > PROB_MIN) { + p = PROB_MIN; + } + if (invert) p = 1.0 - p; + + n->as_MachIf()->_prob = p; +} + //------------------------------update_succ_freq------------------------------- // Update the appropriate frequency associated with block 'b', a succesor of // a block in this loop. diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 52707d038b0..17a5c1f79d1 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -3485,11 +3485,32 @@ bool LibraryCallKit::inline_native_AtomicLong_attemptUpdate() { const TypePtr *adr_type = _gvn.type(adr)->is_ptr(); int alias_idx = C->get_alias_index(adr_type); - Node *result = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal)); - Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(result)); + Node *cas = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal)); + Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(cas)); set_memory(store_proj, alias_idx); + Node *bol = _gvn.transform( new (C, 2) BoolNode( cas, BoolTest::eq ) ); - push(result); + Node *result; + // CMove node is not used to be able fold a possible check code + // after attemptUpdate() call. This code could be transformed + // into CMove node by loop optimizations. + { + RegionNode *r = new (C, 3) RegionNode(3); + result = new (C, 3) PhiNode(r, TypeInt::BOOL); + + Node *iff = create_and_xform_if(control(), bol, PROB_FAIR, COUNT_UNKNOWN); + Node *iftrue = opt_iff(r, iff); + r->init_req(1, iftrue); + result->init_req(1, intcon(1)); + result->init_req(2, intcon(0)); + + set_control(_gvn.transform(r)); + record_for_igvn(r); + + C->set_has_split_ifs(true); // Has chance for split-if optimization + } + + push(_gvn.transform(result)); return true; } diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index f1c15b08344..caa676f6ffd 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -1519,6 +1519,7 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) { Node *bol = iff->in(1); if( bol && bol->req() > 1 && bol->in(1) && ((bol->in(1)->Opcode() == Op_StorePConditional ) || + (bol->in(1)->Opcode() == Op_StoreIConditional ) || (bol->in(1)->Opcode() == Op_StoreLConditional ) || (bol->in(1)->Opcode() == Op_CompareAndSwapI ) || (bol->in(1)->Opcode() == Op_CompareAndSwapL ) || diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 7de433e3aaa..892f5018310 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -82,16 +82,31 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal } } -Node* PhaseMacroExpand::opt_iff(Node* region, Node* iff) { - IfNode *opt_iff = transform_later(iff)->as_If(); +Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) { + Node* cmp; + if (mask != 0) { + Node* and_node = transform_later(new (C, 3) AndXNode(word, MakeConX(mask))); + cmp = transform_later(new (C, 3) CmpXNode(and_node, MakeConX(bits))); + } else { + cmp = word; + } + Node* bol = transform_later(new (C, 2) BoolNode(cmp, BoolTest::ne)); + IfNode* iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN ); + transform_later(iff); - // Fast path taken; set region slot 2 - Node *fast_taken = transform_later( new (C, 1) IfFalseNode(opt_iff) ); - region->init_req(2,fast_taken); // Capture fast-control + // Fast path taken. + Node *fast_taken = transform_later( new (C, 1) IfFalseNode(iff) ); // Fast path not-taken, i.e. slow path - Node *slow_taken = transform_later( new (C, 1) IfTrueNode(opt_iff) ); - return slow_taken; + Node *slow_taken = transform_later( new (C, 1) IfTrueNode(iff) ); + + if (return_fast_path) { + region->init_req(edge, slow_taken); // Capture slow-control + return fast_taken; + } else { + region->init_req(edge, fast_taken); // Capture fast-control + return slow_taken; + } } //--------------------copy_predefined_input_for_runtime_call-------------------- @@ -854,7 +869,7 @@ void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_ad Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) { Node* adr = basic_plus_adr(base, offset); - const TypePtr* adr_type = TypeRawPtr::BOTTOM; + const TypePtr* adr_type = adr->bottom_type()->is_ptr(); Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt); transform_later(value); return value; @@ -1583,12 +1598,194 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) { Node* flock = lock->fastlock_node(); // Make the merge point - Node *region = new (C, 3) RegionNode(3); + Node *region; + Node *mem_phi; + Node *slow_path; - Node *bol = transform_later(new (C, 2) BoolNode(flock,BoolTest::ne)); - Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN ); - // Optimize test; set region slot 2 - Node *slow_path = opt_iff(region,iff); + if (UseOptoBiasInlining) { + /* + * See the full descrition in MacroAssembler::biased_locking_enter(). + * + * if( (mark_word & biased_lock_mask) == biased_lock_pattern ) { + * // The object is biased. + * proto_node = klass->prototype_header; + * o_node = thread | proto_node; + * x_node = o_node ^ mark_word; + * if( (x_node & ~age_mask) == 0 ) { // Biased to the current thread ? + * // Done. + * } else { + * if( (x_node & biased_lock_mask) != 0 ) { + * // The klass's prototype header is no longer biased. + * cas(&mark_word, mark_word, proto_node) + * goto cas_lock; + * } else { + * // The klass's prototype header is still biased. + * if( (x_node & epoch_mask) != 0 ) { // Expired epoch? + * old = mark_word; + * new = o_node; + * } else { + * // Different thread or anonymous biased. + * old = mark_word & (epoch_mask | age_mask | biased_lock_mask); + * new = thread | old; + * } + * // Try to rebias. + * if( cas(&mark_word, old, new) == 0 ) { + * // Done. + * } else { + * goto slow_path; // Failed. + * } + * } + * } + * } else { + * // The object is not biased. + * cas_lock: + * if( FastLock(obj) == 0 ) { + * // Done. + * } else { + * slow_path: + * OptoRuntime::complete_monitor_locking_Java(obj); + * } + * } + */ + + region = new (C, 5) RegionNode(5); + // create a Phi for the memory state + mem_phi = new (C, 5) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); + + Node* fast_lock_region = new (C, 3) RegionNode(3); + Node* fast_lock_mem_phi = new (C, 3) PhiNode( fast_lock_region, Type::MEMORY, TypeRawPtr::BOTTOM); + + // First, check mark word for the biased lock pattern. + Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type()); + + // Get fast path - mark word has the biased lock pattern. + ctrl = opt_bits_test(ctrl, fast_lock_region, 1, mark_node, + markOopDesc::biased_lock_mask_in_place, + markOopDesc::biased_lock_pattern, true); + // fast_lock_region->in(1) is set to slow path. + fast_lock_mem_phi->init_req(1, mem); + + // Now check that the lock is biased to the current thread and has + // the same epoch and bias as Klass::_prototype_header. + + // Special-case a fresh allocation to avoid building nodes: + Node* klass_node = AllocateNode::Ideal_klass(obj, &_igvn); + if (klass_node == NULL) { + Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); + klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) ); + klass_node->init_req(0, ctrl); + } + Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type()); + + Node* thread = transform_later(new (C, 1) ThreadLocalNode()); + Node* cast_thread = transform_later(new (C, 2) CastP2XNode(ctrl, thread)); + Node* o_node = transform_later(new (C, 3) OrXNode(cast_thread, proto_node)); + Node* x_node = transform_later(new (C, 3) XorXNode(o_node, mark_node)); + + // Get slow path - mark word does NOT match the value. + Node* not_biased_ctrl = opt_bits_test(ctrl, region, 3, x_node, + (~markOopDesc::age_mask_in_place), 0); + // region->in(3) is set to fast path - the object is biased to the current thread. + mem_phi->init_req(3, mem); + + + // Mark word does NOT match the value (thread | Klass::_prototype_header). + + + // First, check biased pattern. + // Get fast path - _prototype_header has the same biased lock pattern. + ctrl = opt_bits_test(not_biased_ctrl, fast_lock_region, 2, x_node, + markOopDesc::biased_lock_mask_in_place, 0, true); + + not_biased_ctrl = fast_lock_region->in(2); // Slow path + // fast_lock_region->in(2) - the prototype header is no longer biased + // and we have to revoke the bias on this object. + // We are going to try to reset the mark of this object to the prototype + // value and fall through to the CAS-based locking scheme. + Node* adr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); + Node* cas = new (C, 5) StoreXConditionalNode(not_biased_ctrl, mem, adr, + proto_node, mark_node); + transform_later(cas); + Node* proj = transform_later( new (C, 1) SCMemProjNode(cas)); + fast_lock_mem_phi->init_req(2, proj); + + + // Second, check epoch bits. + Node* rebiased_region = new (C, 3) RegionNode(3); + Node* old_phi = new (C, 3) PhiNode( rebiased_region, TypeX_X); + Node* new_phi = new (C, 3) PhiNode( rebiased_region, TypeX_X); + + // Get slow path - mark word does NOT match epoch bits. + Node* epoch_ctrl = opt_bits_test(ctrl, rebiased_region, 1, x_node, + markOopDesc::epoch_mask_in_place, 0); + // The epoch of the current bias is not valid, attempt to rebias the object + // toward the current thread. + rebiased_region->init_req(2, epoch_ctrl); + old_phi->init_req(2, mark_node); + new_phi->init_req(2, o_node); + + // rebiased_region->in(1) is set to fast path. + // The epoch of the current bias is still valid but we know + // nothing about the owner; it might be set or it might be clear. + Node* cmask = MakeConX(markOopDesc::biased_lock_mask_in_place | + markOopDesc::age_mask_in_place | + markOopDesc::epoch_mask_in_place); + Node* old = transform_later(new (C, 3) AndXNode(mark_node, cmask)); + cast_thread = transform_later(new (C, 2) CastP2XNode(ctrl, thread)); + Node* new_mark = transform_later(new (C, 3) OrXNode(cast_thread, old)); + old_phi->init_req(1, old); + new_phi->init_req(1, new_mark); + + transform_later(rebiased_region); + transform_later(old_phi); + transform_later(new_phi); + + // Try to acquire the bias of the object using an atomic operation. + // If this fails we will go in to the runtime to revoke the object's bias. + cas = new (C, 5) StoreXConditionalNode(rebiased_region, mem, adr, + new_phi, old_phi); + transform_later(cas); + proj = transform_later( new (C, 1) SCMemProjNode(cas)); + + // Get slow path - Failed to CAS. + not_biased_ctrl = opt_bits_test(rebiased_region, region, 4, cas, 0, 0); + mem_phi->init_req(4, proj); + // region->in(4) is set to fast path - the object is rebiased to the current thread. + + // Failed to CAS. + slow_path = new (C, 3) RegionNode(3); + Node *slow_mem = new (C, 3) PhiNode( slow_path, Type::MEMORY, TypeRawPtr::BOTTOM); + + slow_path->init_req(1, not_biased_ctrl); // Capture slow-control + slow_mem->init_req(1, proj); + + // Call CAS-based locking scheme (FastLock node). + + transform_later(fast_lock_region); + transform_later(fast_lock_mem_phi); + + // Get slow path - FastLock failed to lock the object. + ctrl = opt_bits_test(fast_lock_region, region, 2, flock, 0, 0); + mem_phi->init_req(2, fast_lock_mem_phi); + // region->in(2) is set to fast path - the object is locked to the current thread. + + slow_path->init_req(2, ctrl); // Capture slow-control + slow_mem->init_req(2, fast_lock_mem_phi); + + transform_later(slow_path); + transform_later(slow_mem); + // Reset lock's memory edge. + lock->set_req(TypeFunc::Memory, slow_mem); + + } else { + region = new (C, 3) RegionNode(3); + // create a Phi for the memory state + mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); + + // Optimize test; set region slot 2 + slow_path = opt_bits_test(ctrl, region, 2, flock, 0, 0); + mem_phi->init_req(2, mem); + } // Make slow path call CallNode *call = make_slow_call( (CallNode *) lock, OptoRuntime::complete_monitor_enter_Type(), OptoRuntime::complete_monitor_locking_Java(), NULL, slow_path, obj, box ); @@ -1614,16 +1811,11 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) { transform_later(region); _igvn.subsume_node(_fallthroughproj, region); - // create a Phi for the memory state - Node *mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); - Node *memproj = transform_later( new (C, 1) ProjNode(call, TypeFunc::Memory) ); + Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) ); mem_phi->init_req(1, memproj ); - mem_phi->init_req(2, mem); transform_later(mem_phi); - _igvn.hash_delete(_memproj_fallthrough); + _igvn.hash_delete(_memproj_fallthrough); _igvn.subsume_node(_memproj_fallthrough, mem_phi); - - } //------------------------------expand_unlock_node---------------------- @@ -1637,14 +1829,31 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { // No need for a null check on unlock // Make the merge point - RegionNode *region = new (C, 3) RegionNode(3); + Node *region; + Node *mem_phi; + + if (UseOptoBiasInlining) { + // Check for biased locking unlock case, which is a no-op. + // See the full descrition in MacroAssembler::biased_locking_exit(). + region = new (C, 4) RegionNode(4); + // create a Phi for the memory state + mem_phi = new (C, 4) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); + mem_phi->init_req(3, mem); + + Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type()); + ctrl = opt_bits_test(ctrl, region, 3, mark_node, + markOopDesc::biased_lock_mask_in_place, + markOopDesc::biased_lock_pattern); + } else { + region = new (C, 3) RegionNode(3); + // create a Phi for the memory state + mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); + } FastUnlockNode *funlock = new (C, 3) FastUnlockNode( ctrl, obj, box ); funlock = transform_later( funlock )->as_FastUnlock(); - Node *bol = transform_later(new (C, 2) BoolNode(funlock,BoolTest::ne)); - Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN ); // Optimize test; set region slot 2 - Node *slow_path = opt_iff(region,iff); + Node *slow_path = opt_bits_test(ctrl, region, 2, funlock, 0, 0); CallNode *call = make_slow_call( (CallNode *) unlock, OptoRuntime::complete_monitor_exit_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), "complete_monitor_unlocking_C", slow_path, obj, box ); @@ -1666,16 +1875,12 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { transform_later(region); _igvn.subsume_node(_fallthroughproj, region); - // create a Phi for the memory state - Node *mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM); Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) ); mem_phi->init_req(1, memproj ); mem_phi->init_req(2, mem); transform_later(mem_phi); - _igvn.hash_delete(_memproj_fallthrough); + _igvn.hash_delete(_memproj_fallthrough); _igvn.subsume_node(_memproj_fallthrough, mem_phi); - - } //------------------------------expand_macro_nodes---------------------- diff --git a/hotspot/src/share/vm/opto/macro.hpp b/hotspot/src/share/vm/opto/macro.hpp index 89ed2bd2f47..d5c28a461bb 100644 --- a/hotspot/src/share/vm/opto/macro.hpp +++ b/hotspot/src/share/vm/opto/macro.hpp @@ -93,7 +93,7 @@ private: int replace_input(Node *use, Node *oldref, Node *newref); void copy_call_debug_info(CallNode *oldcall, CallNode * newcall); - Node* opt_iff(Node* region, Node* iff); + Node* opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path = false); void copy_predefined_input_for_runtime_call(Node * ctrl, CallNode* oldcall, CallNode* call); CallNode* make_slow_call(CallNode *oldcall, const TypeFunc* slow_call_type, address slow_call, const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1); diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 1fc7915b9d6..582cf2740b9 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -1951,6 +1951,7 @@ void Matcher::find_shared( Node *n ) { // Now hack a few special opcodes switch( n->Opcode() ) { // Handle some opcodes special case Op_StorePConditional: + case Op_StoreIConditional: case Op_StoreLConditional: case Op_CompareAndSwapI: case Op_CompareAndSwapL: diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index d4ba9ef10e8..a042c04b003 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -324,7 +324,7 @@ public: virtual int regnum_to_fpu_offset(int regnum); // Is this branch offset small enough to be addressed by a short branch? - bool is_short_branch_offset(int offset); + bool is_short_branch_offset(int rule, int offset); // Optional scaling for the parameter to the ClearArray/CopyArray node. static const bool init_array_count_is_in_bytes; diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index ea7e062aef9..4cfc0d233f3 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -227,6 +227,14 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { const Type *t_adr = phase->type( address ); if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL + PhaseIterGVN *igvn = phase->is_IterGVN(); + if( can_reshape && igvn != NULL && igvn->_worklist.member(address) ) { + // The address's base and type may change when the address is processed. + // Delay this mem node transformation until the address is processed. + phase->is_IterGVN()->_worklist.push(this); + return NodeSentinel; // caller will return NULL + } + // Avoid independent memory operations Node* old_mem = mem; diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 2b40a676c45..e1a84febc44 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -632,6 +632,17 @@ public: virtual uint ideal_reg() const { return Op_RegFlags; } }; +//------------------------------StoreIConditionalNode--------------------------- +// Conditionally store int to memory, if no change since prior +// load-locked. Sets flags for success or failure of the store. +class StoreIConditionalNode : public LoadStoreNode { +public: + StoreIConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ii ) : LoadStoreNode(c, mem, adr, val, ii) { } + virtual int Opcode() const; + // Produces flags + virtual uint ideal_reg() const { return Op_RegFlags; } +}; + //------------------------------StoreLConditionalNode--------------------------- // Conditionally store long to memory, if no change since prior // load-locked. Sets flags for success or failure of the store. @@ -639,6 +650,8 @@ class StoreLConditionalNode : public LoadStoreNode { public: StoreLConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ll ) : LoadStoreNode(c, mem, adr, val, ll) { } virtual int Opcode() const; + // Produces flags + virtual uint ideal_reg() const { return Op_RegFlags; } }; diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index a3c877077b5..604ab7536ad 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -263,7 +263,7 @@ bool Compile::is_node_getting_a_safepoint( Node* n) { # endif // ENABLE_ZAP_DEAD_LOCALS //------------------------------compute_loop_first_inst_sizes------------------ -// Compute the size of first NumberOfLoopInstrToAlign instructions at head +// Compute the size of first NumberOfLoopInstrToAlign instructions at the top // of a loop. When aligning a loop we need to provide enough instructions // in cpu's fetch buffer to feed decoders. The loop alignment could be // avoided if we have enough instructions in fetch buffer at the head of a loop. @@ -284,34 +284,23 @@ void Compile::compute_loop_first_inst_sizes() { for( uint i=1; i <= last_block; i++ ) { Block *b = _cfg->_blocks[i]; // Check the first loop's block which requires an alignment. - if( b->head()->is_Loop() && - b->code_alignment() > (uint)relocInfo::addr_unit() ) { + if( b->loop_alignment() > (uint)relocInfo::addr_unit() ) { uint sum_size = 0; uint inst_cnt = NumberOfLoopInstrToAlign; - inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt, - _regalloc); - // Check the next fallthrough block if first loop's block does not have - // enough instructions. - if( inst_cnt > 0 && i < last_block ) { - // First, check if the first loop's block contains whole loop. - // LoopNode::LoopBackControl == 2. - Block *bx = _cfg->_bbs[b->pred(2)->_idx]; - // Skip connector blocks (with limit in case of irreducible loops). - int search_limit = 16; - while( bx->is_connector() && search_limit-- > 0) { - bx = _cfg->_bbs[bx->pred(1)->_idx]; - } - if( bx != b ) { // loop body is in several blocks. - Block *nb = NULL; - while( inst_cnt > 0 && i < last_block && nb != bx && - !_cfg->_blocks[i+1]->head()->is_Loop() ) { - i++; - nb = _cfg->_blocks[i]; - inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt, - _regalloc); - } // while( inst_cnt > 0 && i < last_block ) - } // if( bx != b ) - } // if( inst_cnt > 0 && i < last_block ) + inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt, _regalloc); + + // Check subsequent fallthrough blocks if the loop's first + // block(s) does not have enough instructions. + Block *nb = b; + while( inst_cnt > 0 && + i < last_block && + !_cfg->_blocks[i+1]->has_loop_alignment() && + !nb->has_successor(b) ) { + i++; + nb = _cfg->_blocks[i]; + inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt, _regalloc); + } // while( inst_cnt > 0 && i < last_block ) + b->set_first_inst_size(sum_size); } // f( b->head()->is_Loop() ) } // for( i <= last_block ) @@ -332,6 +321,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i uint *jmp_end = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); uint *blk_starts = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks+1); DEBUG_ONLY( uint *jmp_target = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); ) + DEBUG_ONLY( uint *jmp_rule = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); ) blk_starts[0] = 0; // Initialize the sizes to 0 @@ -443,9 +433,9 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i uintptr_t target = blk_starts[bnum]; if( mach->is_pc_relative() ) { int offset = target-(blk_starts[i] + jmp_end[i]); - if (_matcher->is_short_branch_offset(offset)) { + if (_matcher->is_short_branch_offset(mach->rule(), offset)) { // We've got a winner. Replace this branch. - MachNode *replacement = mach->short_branch_version(this); + MachNode* replacement = mach->short_branch_version(this); b->_nodes.map(j, replacement); mach->subsume_by(replacement); @@ -453,6 +443,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i // next pass. jmp_end[i] -= (mach->size(_regalloc) - replacement->size(_regalloc)); DEBUG_ONLY( jmp_target[i] = bnum; ); + DEBUG_ONLY( jmp_rule[i] = mach->rule(); ); } } else { #ifndef PRODUCT @@ -510,7 +501,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i // Get the size of the block uint blk_size = adr - blk_starts[i]; - // When the next block starts a loop, we may insert pad NOP + // When the next block is the top of a loop, we may insert pad NOP // instructions. Block *nb = _cfg->_blocks[i+1]; int current_offset = blk_starts[i] + blk_size; @@ -524,10 +515,10 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i for( i=0; i<_cfg->_num_blocks; i++ ) { // For all blocks if( jmp_target[i] != 0 ) { int offset = blk_starts[jmp_target[i]]-(blk_starts[i] + jmp_end[i]); - if (!_matcher->is_short_branch_offset(offset)) { + if (!_matcher->is_short_branch_offset(jmp_rule[i], offset)) { tty->print_cr("target (%d) - jmp_end(%d) = offset (%d), jmp_block B%d, target_block B%d", blk_starts[jmp_target[i]], blk_starts[i] + jmp_end[i], offset, i, jmp_target[i]); } - assert(_matcher->is_short_branch_offset(offset), "Displacement too large for short jmp"); + assert(_matcher->is_short_branch_offset(jmp_rule[i], offset), "Displacement too large for short jmp"); } } #endif @@ -1069,7 +1060,7 @@ void Compile::Fill_buffer() { // If this machine supports different size branch offsets, then pre-compute // the length of the blocks - if( _matcher->is_short_branch_offset(0) ) { + if( _matcher->is_short_branch_offset(-1, 0) ) { Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req); labels_not_set = false; } @@ -1380,8 +1371,8 @@ void Compile::Fill_buffer() { } // End for all instructions in block - // If the next block _starts_ a loop, pad this block out to align - // the loop start a little. Helps prevent pipe stalls at loop starts + // If the next block is the top of a loop, pad this block out to align + // the loop top a little. Helps prevent pipe stalls at loop back branches. int nop_size = (new (this) MachNopNode())->size(_regalloc); if( i<_cfg->_num_blocks-1 ) { Block *nb = _cfg->_blocks[i+1]; diff --git a/hotspot/src/share/vm/opto/phase.cpp b/hotspot/src/share/vm/opto/phase.cpp index 5e046dab061..8bed29122f0 100644 --- a/hotspot/src/share/vm/opto/phase.cpp +++ b/hotspot/src/share/vm/opto/phase.cpp @@ -46,7 +46,7 @@ elapsedTimer Phase::_t_output; #ifndef PRODUCT elapsedTimer Phase::_t_graphReshaping; elapsedTimer Phase::_t_scheduler; -elapsedTimer Phase::_t_removeEmptyBlocks; +elapsedTimer Phase::_t_blockOrdering; elapsedTimer Phase::_t_macroExpand; elapsedTimer Phase::_t_peephole; elapsedTimer Phase::_t_codeGeneration; @@ -128,7 +128,7 @@ void Phase::print_timers() { tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc); } tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds()); - tty->print_cr (" removeEmpty : %3.3f sec", Phase::_t_removeEmptyBlocks.seconds()); + tty->print_cr (" blockOrdering: %3.3f sec", Phase::_t_blockOrdering.seconds()); tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds()); tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds()); tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds()); @@ -137,7 +137,7 @@ void Phase::print_timers() { (DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) + Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() + Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() + - Phase::_t_registerAllocation.seconds() + Phase::_t_removeEmptyBlocks.seconds() + + Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() + Phase::_t_macroExpand.seconds() + Phase::_t_peephole.seconds() + Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds(); double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0; diff --git a/hotspot/src/share/vm/opto/phase.hpp b/hotspot/src/share/vm/opto/phase.hpp index bee7dfef70d..788f07acc71 100644 --- a/hotspot/src/share/vm/opto/phase.hpp +++ b/hotspot/src/share/vm/opto/phase.hpp @@ -40,16 +40,12 @@ public: Optimistic, // Optimistic analysis phase GVN, // Pessimistic global value numbering phase Ins_Select, // Instruction selection phase - Copy_Elimination, // Copy Elimination - Dead_Code_Elimination, // DCE and compress Nodes - Conditional_Constant, // Conditional Constant Propagation CFG, // Build a CFG - DefUse, // Build Def->Use chains + BlockLayout, // Linear ordering of blocks Register_Allocation, // Register allocation, duh LIVE, // Dragon-book LIVE range problem Interference_Graph, // Building the IFG Coalesce, // Coalescing copies - Conditional_CProp, // Conditional Constant Propagation Ideal_Loop, // Find idealized trip-counted loops Macro_Expand, // Expand macro nodes Peephole, // Apply peephole optimizations @@ -80,7 +76,7 @@ protected: #ifndef PRODUCT static elapsedTimer _t_graphReshaping; static elapsedTimer _t_scheduler; - static elapsedTimer _t_removeEmptyBlocks; + static elapsedTimer _t_blockOrdering; static elapsedTimer _t_macroExpand; static elapsedTimer _t_peephole; static elapsedTimer _t_codeGeneration; diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index 6db3a76d5f7..003df4c48b7 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -53,6 +53,7 @@ Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) { // Bail rather than abort int ireg = def->ideal_reg(); if( ireg == 0 || ireg == Op_RegFlags ) { + assert(false, "attempted to spill a non-spillable item"); C->record_method_not_compilable("attempted to spill a non-spillable item"); return NULL; } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 3e9b66ba32e..f433a125535 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -3541,7 +3541,7 @@ intptr_t TypeNarrowOop::get_con() const { #ifndef PRODUCT void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { - tty->print("narrowoop: "); + st->print("narrowoop: "); _ooptype->dump2(d, depth, st); } #endif diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 69bc06a7384..3d3f3ddd883 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -1183,6 +1183,9 @@ inline bool Type::is_floatingpoint() const { #define RShiftXNode RShiftLNode // For card marks and hashcodes #define URShiftXNode URShiftLNode +// UseOptoBiasInlining +#define XorXNode XorLNode +#define StoreXConditionalNode StoreLConditionalNode // Opcodes #define Op_LShiftX Op_LShiftL #define Op_AndX Op_AndL @@ -1222,6 +1225,9 @@ inline bool Type::is_floatingpoint() const { #define RShiftXNode RShiftINode // For card marks and hashcodes #define URShiftXNode URShiftINode +// UseOptoBiasInlining +#define XorXNode XorINode +#define StoreXConditionalNode StoreIConditionalNode // Opcodes #define Op_LShiftX Op_LShiftI #define Op_AndX Op_AndI diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index b8bf9f1cd9c..fa2ba23383b 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1365,6 +1365,9 @@ void Arguments::set_aggressive_opts_flags() { if (AggressiveOpts && FLAG_IS_DEFAULT(SpecialArraysEquals)) { FLAG_SET_DEFAULT(SpecialArraysEquals, true); } + if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) { + FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500); + } #endif if (AggressiveOpts) { @@ -2625,6 +2628,12 @@ jint Arguments::parse(const JavaVMInitArgs* args) { FLAG_SET_DEFAULT(UseBiasedLocking, false); #endif /* CC_INTERP */ +#ifdef COMPILER2 + if (!UseBiasedLocking || EmitSync != 0) { + UseOptoBiasInlining = false; + } +#endif + if (PrintCommandLineFlags) { CommandLineFlags::printSetFlags(); } diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 6baf659d0ff..e84d6d3ad8b 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -83,12 +83,12 @@ void RegisterMap::print_on(outputStream* st) const { intptr_t* src = (intptr_t*) location(r); if (src != NULL) { - r->print(); - tty->print(" [" INTPTR_FORMAT "] = ", src); + r->print_on(st); + st->print(" [" INTPTR_FORMAT "] = ", src); if (((uintptr_t)src & (sizeof(*src)-1)) != 0) { - tty->print_cr(""); + st->print_cr(""); } else { - tty->print_cr(INTPTR_FORMAT, *src); + st->print_cr(INTPTR_FORMAT, *src); } } } diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 71ab720f028..a9d7a72f1cd 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -263,7 +263,7 @@ void VMError::report(outputStream* st) { st->print("# java.lang.OutOfMemoryError: "); if (_size) { st->print("requested "); - sprintf(buf,"%d",_size); + sprintf(buf,SIZE_FORMAT,_size); st->print(buf); st->print(" bytes"); if (_message != NULL) { diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 617465552f9..a0629ba363f 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -13,3 +13,4 @@ eac46d1eb7f0935ba04f1c7929ec15423fd0309e jdk7-b35 c84ca638db42a8b6b227b4e3b63bca192c5ca634 jdk7-b36 af49591bc486d82aa04b832257de0d18adc9af52 jdk7-b37 e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38 +831b80be6cea8e7d7da197ccdac5fd4c701a5033 jdk7-b39 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index bd52eb7b738..f578d68a15c 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -13,3 +13,4 @@ b0f01c2508b690dd225298edfec70b5e8b8dc367 jdk7-b35 f60187f44a0d62906a5e2f6bd0989b5b24c1ca1e jdk7-b36 a2a6f9edf761934faf59ea60d7fe7178371302cd jdk7-b37 9ce439969184c753a9ba3caf8ed277b05230f2e5 jdk7-b38 +077bc9b1b035a409a76bd5366f73ed9dd9846934 jdk7-b39 diff --git a/jdk/.hgtags b/jdk/.hgtags index d9b8755cd4d..8b57d704d5d 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -13,3 +13,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35 134fd1a656ea85acd1f97f6700f75029b9b472a0 jdk7-b36 14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37 cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38 +4e51997582effa006dde5c6d8b8820b2045b9c7f jdk7-b39 diff --git a/jdk/make/netbeans/jmx/build.xml b/jdk/make/netbeans/jmx/build.xml index 6e2696ebb8f..e306b8ea40a 100644 --- a/jdk/make/netbeans/jmx/build.xml +++ b/jdk/make/netbeans/jmx/build.xml @@ -44,13 +44,13 @@ - - + @@ -58,13 +58,13 @@ - + @@ -96,7 +96,7 @@ - + - - @@ -131,7 +131,7 @@ - @@ -144,7 +144,7 @@ - + diff --git a/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java b/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java index e1761011f0e..09a7a03a42d 100644 --- a/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java +++ b/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java @@ -141,7 +141,7 @@ public class LeaseManager { } private final Runnable callback; - private ScheduledFuture scheduled; // If null, the lease has expired. + private ScheduledFuture scheduled; // If null, the lease has expired. private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1, diff --git a/jdk/src/share/classes/com/sun/jmx/event/LeaseRenewer.java b/jdk/src/share/classes/com/sun/jmx/event/LeaseRenewer.java index b3f7c7fee07..8ba6877221e 100644 --- a/jdk/src/share/classes/com/sun/jmx/event/LeaseRenewer.java +++ b/jdk/src/share/classes/com/sun/jmx/event/LeaseRenewer.java @@ -128,7 +128,7 @@ public class LeaseRenewer { }; private final Callable doRenew; - private ScheduledFuture future; + private ScheduledFuture future; private boolean closed = false; private long nextRenewTime; diff --git a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java index 7da3406b911..3d80a09eccb 100644 --- a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java @@ -247,7 +247,7 @@ public class DefaultMBeanServerInterceptor MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException { - Class theClass; + Class theClass; if (className == null) { final RuntimeException wrapped = @@ -327,7 +327,7 @@ public class DefaultMBeanServerInterceptor // ------------------------------ // ------------------------------ - Class theClass = object.getClass(); + Class theClass = object.getClass(); Introspector.checkCompliance(theClass); @@ -808,9 +808,8 @@ public class DefaultMBeanServerInterceptor // on each specific attribute // allowedAttributes = new AttributeList(attributes.size()); - for (Iterator i = attributes.iterator(); i.hasNext();) { + for (Attribute attribute : attributes.asList()) { try { - Attribute attribute = (Attribute) i.next(); checkMBeanPermission(mbeanServerName, classname, attribute.getName(), name, "setAttribute"); allowedAttributes.add(attribute); @@ -1857,7 +1856,7 @@ public class DefaultMBeanServerInterceptor } } - private static void checkMBeanTrustPermission(final Class theClass) + private static void checkMBeanTrustPermission(final Class theClass) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java index 35311699d8d..011bb2d26ac 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java @@ -136,14 +136,14 @@ final class ClassLoaderRepositorySupport new Hashtable(10); // from javax.management.loading.DefaultLoaderRepository - public final Class loadClass(String className) + public final Class loadClass(String className) throws ClassNotFoundException { return loadClass(loaders, className, null, null); } // from javax.management.loading.DefaultLoaderRepository - public final Class loadClassWithout(ClassLoader without, String className) + public final Class loadClassWithout(ClassLoader without, String className) throws ClassNotFoundException { if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { MBEANSERVER_LOGGER.logp(Level.FINER, @@ -167,7 +167,7 @@ final class ClassLoaderRepositorySupport } - public final Class loadClassBefore(ClassLoader stop, String className) + public final Class loadClassBefore(ClassLoader stop, String className) throws ClassNotFoundException { if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { MBEANSERVER_LOGGER.logp(Level.FINER, @@ -187,10 +187,10 @@ final class ClassLoaderRepositorySupport } - private Class loadClass(final LoaderEntry list[], - final String className, - final ClassLoader without, - final ClassLoader stop) + private Class loadClass(final LoaderEntry list[], + final String className, + final ClassLoader without, + final ClassLoader stop) throws ClassNotFoundException { final int size = list.length; for(int i=0; i getOpenReturnType() { return returnMapping.getOpenType(); } - OpenType[] getOpenParameterTypes() { - final OpenType[] types = new OpenType[paramMappings.length]; + OpenType[] getOpenParameterTypes() { + final OpenType[] types = new OpenType[paramMappings.length]; for (int i = 0; i < paramMappings.length; i++) types[i] = paramMappings[i].getOpenType(); return types; diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java index b86b2e00128..1b653c28eaf 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java @@ -26,7 +26,8 @@ package com.sun.jmx.mbeanserver; import static com.sun.jmx.mbeanserver.Util.*; -import java.lang.annotation.ElementType; +import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName; + import javax.management.openmbean.MXBeanMappingClass; import static javax.management.openmbean.SimpleType.*; @@ -120,7 +121,7 @@ import javax.management.openmbean.TabularType; */ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { static abstract class NonNullMXBeanMapping extends MXBeanMapping { - NonNullMXBeanMapping(Type javaType, OpenType openType) { + NonNullMXBeanMapping(Type javaType, OpenType openType) { super(javaType, openType); } @@ -195,15 +196,15 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { static { /* Set up the mappings for Java types that map to SimpleType. */ - final OpenType[] simpleTypes = { + final OpenType[] simpleTypes = { BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE, DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING, VOID, }; for (int i = 0; i < simpleTypes.length; i++) { - final OpenType t = simpleTypes[i]; - Class c; + final OpenType t = simpleTypes[i]; + Class c; try { c = Class.forName(t.getClassName(), false, ObjectName.class.getClassLoader()); @@ -224,7 +225,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { if (primitiveType != void.class) { final Class primitiveArrayType = Array.newInstance(primitiveType, 0).getClass(); - final OpenType primitiveArrayOpenType = + final OpenType primitiveArrayOpenType = ArrayType.getPrimitiveArrayType(primitiveArrayType); final MXBeanMapping primitiveArrayMapping = new IdentityMapping(primitiveArrayType, @@ -247,8 +248,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { public synchronized MXBeanMapping mappingForType(Type objType, MXBeanMappingFactory factory) throws OpenDataException { - if (inProgress.containsKey(objType)) - throw new OpenDataException("Recursive data structure"); + if (inProgress.containsKey(objType)) { + throw new OpenDataException( + "Recursive data structure, including " + typeName(objType)); + } MXBeanMapping mapping; @@ -259,6 +262,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { inProgress.put(objType, objType); try { mapping = makeMapping(objType, factory); + } catch (OpenDataException e) { + throw openDataException("Cannot convert type: " + typeName(objType), e); } finally { inProgress.remove(objType); } @@ -285,13 +290,13 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { Type componentType = ((GenericArrayType) objType).getGenericComponentType(); return makeArrayOrCollectionMapping(objType, componentType, factory); - } else if (objType instanceof Class) { + } else if (objType instanceof Class) { Class objClass = (Class) objType; if (objClass.isEnum()) { // Huge hack to avoid compiler warnings here. The ElementType // parameter is ignored but allows us to obtain a type variable // T that matches >. - return makeEnumMapping((Class) objClass, ElementType.class); + return makeEnumMapping((Class) objClass, ElementType.class); } else if (objClass.isArray()) { Type componentType = objClass.getComponentType(); return makeArrayOrCollectionMapping(objClass, componentType, @@ -354,7 +359,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { } private static > MXBeanMapping - makeEnumMapping(Class enumClass, Class fake) { + makeEnumMapping(Class enumClass, Class fake) { return new EnumMapping(Util.>cast(enumClass)); } @@ -411,17 +416,17 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { MXBeanMappingFactory factory) throws OpenDataException { - final String objTypeName = objType.toString(); + final String objTypeName = typeName(objType); final MXBeanMapping keyMapping = factory.mappingForType(keyType, factory); final MXBeanMapping valueMapping = factory.mappingForType(valueType, factory); - final OpenType keyOpenType = keyMapping.getOpenType(); - final OpenType valueOpenType = valueMapping.getOpenType(); + final OpenType keyOpenType = keyMapping.getOpenType(); + final OpenType valueOpenType = valueMapping.getOpenType(); final CompositeType rowType = new CompositeType(objTypeName, objTypeName, keyValueArray, keyValueArray, - new OpenType[] {keyOpenType, valueOpenType}); + new OpenType[] {keyOpenType, valueOpenType}); final TabularType tabularType = new TabularType(objTypeName, objTypeName, rowType, keyArray); return new TabularMapping(objType, sortedMap, tabularType, @@ -440,8 +445,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { final Type rawType = objType.getRawType(); - if (rawType instanceof Class) { - Class c = (Class) rawType; + if (rawType instanceof Class) { + Class c = (Class) rawType; if (c == List.class || c == Set.class || c == SortedSet.class) { Type[] actuals = objType.getActualTypeArguments(); assert(actuals.length == 1); @@ -468,7 +473,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { return new MXBeanRefMapping(t); } - private MXBeanMapping makeCompositeMapping(Class c, + private MXBeanMapping makeCompositeMapping(Class c, MXBeanMappingFactory factory) throws OpenDataException { @@ -514,7 +519,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { final Method[] getters = new Method[nitems]; final String[] itemNames = new String[nitems]; - final OpenType[] openTypes = new OpenType[nitems]; + final OpenType[] openTypes = new OpenType[nitems]; int i = 0; for (Map.Entry entry : getterMap.entrySet()) { itemNames[i] = entry.getKey(); @@ -546,7 +551,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { can be directly represented by an ArrayType, and an int needs no mapping because reflection takes care of it. */ private static final class IdentityMapping extends NonNullMXBeanMapping { - IdentityMapping(Type targetType, OpenType openType) { + IdentityMapping(Type targetType, OpenType openType) { super(targetType, openType); } @@ -576,7 +581,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { @Override final Object toNonNullOpenValue(Object value) { - return ((Enum) value).name(); + return ((Enum) value).name(); } @Override @@ -595,7 +600,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { private static final class ArrayMapping extends NonNullMXBeanMapping { ArrayMapping(Type targetType, - ArrayType openArrayType, Class openArrayClass, + ArrayType openArrayType, Class openArrayClass, MXBeanMapping elementMapping) { super(targetType, openArrayType); this.elementMapping = elementMapping; @@ -623,7 +628,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { if (javaType instanceof GenericArrayType) { componentType = ((GenericArrayType) javaType).getGenericComponentType(); - } else if (javaType instanceof Class && + } else if (javaType instanceof Class && ((Class) javaType).isArray()) { componentType = ((Class) javaType).getComponentType(); } else { @@ -651,8 +656,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { private static final class CollectionMapping extends NonNullMXBeanMapping { CollectionMapping(Type targetType, - ArrayType openArrayType, - Class openArrayClass, + ArrayType openArrayType, + Class openArrayClass, MXBeanMapping elementMapping) { super(targetType, openArrayType); this.elementMapping = elementMapping; @@ -662,26 +667,28 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { and all Sets to TreeSet. (TreeSet because it is a SortedSet, so works for both Set and SortedSet.) */ Type raw = ((ParameterizedType) targetType).getRawType(); - Class c = (Class) raw; + Class c = (Class) raw; + final Class collC; if (c == List.class) - collectionClass = ArrayList.class; + collC = ArrayList.class; else if (c == Set.class) - collectionClass = HashSet.class; + collC = HashSet.class; else if (c == SortedSet.class) - collectionClass = TreeSet.class; + collC = TreeSet.class; else { // can't happen assert(false); - collectionClass = null; + collC = null; } + collectionClass = Util.cast(collC); } @Override final Object toNonNullOpenValue(Object value) throws OpenDataException { - final Collection valueCollection = (Collection) value; - if (valueCollection instanceof SortedSet) { - Comparator comparator = - ((SortedSet) valueCollection).comparator(); + final Collection valueCollection = (Collection) value; + if (valueCollection instanceof SortedSet) { + Comparator comparator = + ((SortedSet) valueCollection).comparator(); if (comparator != null) { final String msg = "Cannot convert SortedSet with non-null comparator: " + @@ -725,7 +732,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { elementMapping.checkReconstructible(); } - private final Class collectionClass; + private final Class> collectionClass; private final MXBeanMapping elementMapping; } @@ -794,8 +801,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { @Override final Object toNonNullOpenValue(Object value) throws OpenDataException { final Map valueMap = cast(value); - if (valueMap instanceof SortedMap) { - Comparator comparator = ((SortedMap) valueMap).comparator(); + if (valueMap instanceof SortedMap) { + Comparator comparator = ((SortedMap) valueMap).comparator(); if (comparator != null) { final String msg = "Cannot convert SortedMap with non-null comparator: " + @@ -806,7 +813,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { final TabularType tabularType = (TabularType) getOpenType(); final TabularData table = new TabularDataSupport(tabularType); final CompositeType rowType = tabularType.getRowType(); - for (Map.Entry entry : valueMap.entrySet()) { + for (Map.Entry entry : valueMap.entrySet()) { final Object openKey = keyMapping.toOpenValue(entry.getKey()); final Object openValue = valueMapping.toOpenValue(entry.getValue()); final CompositeData row; @@ -852,7 +859,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { } private final class CompositeMapping extends NonNullMXBeanMapping { - CompositeMapping(Class targetClass, + CompositeMapping(Class targetClass, CompositeType compositeType, String[] itemNames, Method[] getters, @@ -901,7 +908,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { if (compositeBuilder != null) return; - Class targetClass = (Class) getJavaType(); + Class targetClass = (Class) getJavaType(); /* In this 2D array, each subarray is a set of builders where there is no point in consulting the ones after the first if the first refuses. */ @@ -924,6 +931,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { concatenating each Builder's explanation of why it isn't applicable. */ final StringBuilder whyNots = new StringBuilder(); + Throwable possibleCause = null; find: for (CompositeBuilder[] relatedBuilders : builders) { for (int i = 0; i < relatedBuilders.length; i++) { @@ -933,6 +941,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { foundBuilder = builder; break find; } + Throwable cause = builder.possibleCause(); + if (cause != null) + possibleCause = cause; if (whyNot.length() > 0) { if (whyNots.length() > 0) whyNots.append("; "); @@ -943,10 +954,12 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { } } if (foundBuilder == null) { - final String msg = + String msg = "Do not know how to make a " + targetClass.getName() + " from a CompositeData: " + whyNots; - throw new InvalidObjectException(msg); + if (possibleCause != null) + msg += ". Remaining exceptions show a POSSIBLE cause."; + throw invalidObjectException(msg, possibleCause); } compositeBuilder = foundBuilder; } @@ -973,7 +986,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { /** Converts from a CompositeData to an instance of the targetClass. */ private static abstract class CompositeBuilder { - CompositeBuilder(Class targetClass, String[] itemNames) { + CompositeBuilder(Class targetClass, String[] itemNames) { this.targetClass = targetClass; this.itemNames = itemNames; } @@ -994,6 +1007,16 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { abstract String applicable(Method[] getters) throws InvalidObjectException; + /** If the subclass returns an explanation of why it is not applicable, + it can additionally indicate an exception with details. This is + potentially confusing, because the real problem could be that one + of the other subclasses is supposed to be applicable but isn't. + But the advantage of less information loss probably outweighs the + disadvantage of possible confusion. */ + Throwable possibleCause() { + return null; + } + abstract Object fromCompositeData(CompositeData cd, String[] itemNames, MXBeanMapping[] converters) @@ -1008,7 +1031,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { private static final class CompositeBuilderViaFrom extends CompositeBuilder { - CompositeBuilderViaFrom(Class targetClass, String[] itemNames) { + CompositeBuilderViaFrom(Class targetClass, String[] itemNames) { super(targetClass, itemNames); } @@ -1018,8 +1041,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { Class targetClass = getTargetClass(); try { Method fromMethod = - targetClass.getMethod("from", - new Class[] {CompositeData.class}); + targetClass.getMethod("from", CompositeData.class); if (!Modifier.isStatic(fromMethod.getModifiers())) { final String msg = @@ -1030,8 +1052,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { if (fromMethod.getReturnType() != getTargetClass()) { final String msg = "Method from(CompositeData) returns " + - fromMethod.getReturnType().getName() + - " not " + targetClass.getName(); + typeName(fromMethod.getReturnType()) + + " not " + typeName(targetClass); throw new InvalidObjectException(msg); } @@ -1071,7 +1093,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { If all the getters are OK, then the "applicable" method will return an empty string and the other builders will be tried. */ private static class CompositeBuilderCheckGetters extends CompositeBuilder { - CompositeBuilderCheckGetters(Class targetClass, String[] itemNames, + CompositeBuilderCheckGetters(Class targetClass, String[] itemNames, MXBeanMapping[] getterConverters) { super(targetClass, itemNames); this.getterConverters = getterConverters; @@ -1082,6 +1104,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { try { getterConverters[i].checkReconstructible(); } catch (InvalidObjectException e) { + possibleCause = e; return "method " + getters[i].getName() + " returns type " + "that cannot be mapped back from OpenData"; } @@ -1089,6 +1112,11 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { return ""; } + @Override + Throwable possibleCause() { + return possibleCause; + } + final Object fromCompositeData(CompositeData cd, String[] itemNames, MXBeanMapping[] converters) { @@ -1096,6 +1124,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { } private final MXBeanMapping[] getterConverters; + private Throwable possibleCause; } /** Builder for when the target class has a setter for every getter. */ @@ -1115,7 +1144,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { Method[] setters = new Method[getters.length]; for (int i = 0; i < getters.length; i++) { Method getter = getters[i]; - Class returnType = getter.getReturnType(); + Class returnType = getter.getReturnType(); String name = propertyName(getter); String setterName = "set" + name; Method setter; @@ -1163,7 +1192,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { private static final class CompositeBuilderViaConstructor extends CompositeBuilder { - CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) { + CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) { super(targetClass, itemNames); } @@ -1171,7 +1200,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { final Class propertyNamesClass = ConstructorProperties.class; - Class targetClass = getTargetClass(); + Class targetClass = getTargetClass(); Constructor[] constrs = targetClass.getConstructors(); // Applicable if and only if there are any annotated constructors @@ -1226,10 +1255,16 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { for (int i = 0; i < propertyNames.length; i++) { String propertyName = propertyNames[i]; if (!getterMap.containsKey(propertyName)) { - final String msg = + String msg = "@ConstructorProperties includes name " + propertyName + - " which does not correspond to a property: " + - constr; + " which does not correspond to a property"; + for (String getterName : getterMap.keySet()) { + if (getterName.equalsIgnoreCase(propertyName)) { + msg += " (differs only in case from property " + + getterName + ")"; + } + } + msg += ": " + constr; throw new InvalidObjectException(msg); } int getterIndex = getterMap.get(propertyName); @@ -1384,12 +1419,12 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { private static final class CompositeBuilderViaProxy extends CompositeBuilder { - CompositeBuilderViaProxy(Class targetClass, String[] itemNames) { + CompositeBuilderViaProxy(Class targetClass, String[] itemNames) { super(targetClass, itemNames); } String applicable(Method[] getters) { - Class targetClass = getTargetClass(); + Class targetClass = getTargetClass(); if (!targetClass.isInterface()) return "not an interface"; Set methods = @@ -1401,7 +1436,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { String bad = null; for (Method m : methods) { String mname = m.getName(); - Class[] mparams = m.getParameterTypes(); + Class[] mparams = m.getParameterTypes(); try { Method om = Object.class.getMethod(mname, mparams); if (!Modifier.isPublic(om.getModifiers())) @@ -1422,10 +1457,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { final Object fromCompositeData(CompositeData cd, String[] itemNames, MXBeanMapping[] converters) { - final Class targetClass = getTargetClass(); + final Class targetClass = getTargetClass(); return Proxy.newProxyInstance(targetClass.getClassLoader(), - new Class[] {targetClass}, + new Class[] {targetClass}, new CompositeDataInvocationHandler(cd)); } } @@ -1447,9 +1482,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { return openDataException(cause.getMessage(), cause); } - static void mustBeComparable(Class collection, Type element) + static void mustBeComparable(Class collection, Type element) throws OpenDataException { - if (!(element instanceof Class) + if (!(element instanceof Class) || !Comparable.class.isAssignableFrom((Class) element)) { final String msg = "Parameter class " + element + " of " + diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java index 52783fd5a60..da4209cd2b3 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -115,7 +115,7 @@ public class Introspector { * Dynamic MBeans, false otherwise. * **/ - public static final boolean isDynamic(final Class c) { + public static final boolean isDynamic(final Class c) { // Check if the MBean implements the DynamicMBean interface return javax.management.DynamicMBean.class.isAssignableFrom(c); } @@ -134,7 +134,7 @@ public class Introspector { * MBeanServer. * **/ - public static void testCreation(Class c) + public static void testCreation(Class c) throws NotCompliantMBeanException { // Check if the class is a concrete class final int mods = c.getModifiers(); @@ -143,7 +143,7 @@ public class Introspector { } // Check if the MBean has a public constructor - final Constructor[] consList = c.getConstructors(); + final Constructor[] consList = c.getConstructors(); if (consList.length == 0) { throw new NotCompliantMBeanException("MBean class must have public constructor"); } @@ -253,7 +253,7 @@ public class Introspector { * @exception NotCompliantMBeanException The specified class is not a * JMX compliant MBean */ - public static MBeanInfo testCompliance(Class baseClass) + public static MBeanInfo testCompliance(Class baseClass) throws NotCompliantMBeanException { // ------------------------------ @@ -267,7 +267,7 @@ public class Introspector { return testCompliance(baseClass, null); } - public static void testComplianceMXBeanInterface(Class interfaceClass, + public static void testComplianceMXBeanInterface(Class interfaceClass, MXBeanMappingFactory factory) throws NotCompliantMBeanException { MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass); @@ -596,10 +596,10 @@ public class Introspector { ss[i] = (String) annotationToField(xx[i]); return ss; } - if (x instanceof Class) + if (x instanceof Class) return ((Class) x).getName(); - if (x instanceof Enum) - return ((Enum) x).name(); + if (x instanceof Enum) + return ((Enum) x).name(); // The only other possibility is that the value is another // annotation, or that the language has evolved since this code // was written. We don't allow for either of those currently. diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java index 777cd1cce65..14ee0ac5279 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java @@ -33,6 +33,7 @@ import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedExceptionAction; import java.util.Iterator; +import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -1144,7 +1145,7 @@ public final class JmxMBeanServer // This call requires MBeanPermission 'getClassLoaderRepository' final ClassLoaderRepository clr = getClassLoaderRepository(); - Class theClass; + Class theClass; try { if (clr == null) throw new ClassNotFoundException(className); theClass = clr.loadClass(className); @@ -1457,23 +1458,22 @@ public final class JmxMBeanServer */ private AttributeList cloneAttributeList(AttributeList list) { if (list != null) { + List alist = list.asList(); if (!list.getClass().equals(AttributeList.class)) { // Create new attribute list // - AttributeList newList = new AttributeList(list.size()); + AttributeList newList = new AttributeList(alist.size()); // Iterate through list and replace non JMX attributes // - for (Iterator i = list.iterator(); i.hasNext(); ) { - Attribute attribute = (Attribute) i.next(); + for (Attribute attribute : alist) newList.add(cloneAttribute(attribute)); - } return newList; } else { // Iterate through list and replace non JMX attributes // - for (int i = 0; i < list.size(); i++) { - Attribute attribute = (Attribute) list.get(i); + for (int i = 0; i < alist.size(); i++) { + Attribute attribute = alist.get(i); if (!attribute.getClass().equals(Attribute.class)) { list.set(i, cloneAttribute(attribute)); } diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java index 019793b8d85..789fd661aa9 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java @@ -70,7 +70,7 @@ public class MBeanInstantiator { * instantiate an MBean of this class in the MBeanServer. * e.g. it must have a public constructor, be a concrete class... */ - public void testCreation(Class c) throws NotCompliantMBeanException { + public void testCreation(Class c) throws NotCompliantMBeanException { Introspector.testCreation(c); } @@ -78,10 +78,10 @@ public class MBeanInstantiator { * Loads the class with the specified name using this object's * Default Loader Repository. **/ - public Class findClassWithDefaultLoaderRepository(String className) + public Class findClassWithDefaultLoaderRepository(String className) throws ReflectionException { - Class theClass; + Class theClass; if (className == null) { throw new RuntimeOperationsException(new IllegalArgumentException("The class name cannot be null"), @@ -105,7 +105,7 @@ public class MBeanInstantiator { * Gets the class for the specified class name using the MBean * Interceptor's classloader */ - public Class findClass(String className, ClassLoader loader) + public Class findClass(String className, ClassLoader loader) throws ReflectionException { return loadClass(className,loader); @@ -115,7 +115,7 @@ public class MBeanInstantiator { * Gets the class for the specified class name using the specified * class loader */ - public Class findClass(String className, ObjectName aLoader) + public Class findClass(String className, ObjectName aLoader) throws ReflectionException, InstanceNotFoundException { if (aLoader == null) @@ -140,14 +140,14 @@ public class MBeanInstantiator { * Return an array of Class corresponding to the given signature, using * the specified class loader. */ - public Class[] findSignatureClasses(String signature[], - ClassLoader loader) - throws ReflectionException { + public Class[] findSignatureClasses(String signature[], + ClassLoader loader) + throws ReflectionException { if (signature == null) return null; final ClassLoader aLoader = loader; final int length= signature.length; - final Class tab[]=new Class[length]; + final Class tab[]=new Class[length]; if (length == 0) return tab; try { @@ -156,7 +156,7 @@ public class MBeanInstantiator { // forth) // - final Class primCla = primitiveClasses.get(signature[i]); + final Class primCla = primitiveClasses.get(signature[i]); if (primCla != null) { tab[i] = primCla; continue; @@ -203,14 +203,14 @@ public class MBeanInstantiator { * Instantiates an object given its class, using its empty constructor. * The call returns a reference to the newly created object. */ - public Object instantiate(Class theClass) + public Object instantiate(Class theClass) throws ReflectionException, MBeanException { Object moi; // ------------------------------ // ------------------------------ - Constructor cons = findConstructor(theClass, null); + Constructor cons = findConstructor(theClass, null); if (cons == null) { throw new ReflectionException(new NoSuchMethodException("No such constructor")); @@ -257,14 +257,14 @@ public class MBeanInstantiator { * signature of its constructor The call returns a reference to * the newly created object. */ - public Object instantiate(Class theClass, Object params[], + public Object instantiate(Class theClass, Object params[], String signature[], ClassLoader loader) throws ReflectionException, MBeanException { // Instantiate the new object // ------------------------------ // ------------------------------ - final Class[] tab; + final Class[] tab; Object moi; try { // Build the signature of the method @@ -283,7 +283,7 @@ public class MBeanInstantiator { } // Query the metadata service to get the right constructor - Constructor cons = findConstructor(theClass, tab); + Constructor cons = findConstructor(theClass, tab); if (cons == null) { throw new ReflectionException(new @@ -407,7 +407,7 @@ public class MBeanInstantiator { throw new RuntimeOperationsException(new IllegalArgumentException(), "Null className passed in parameter"); } - Class theClass; + Class theClass; if (loaderName == null) { // Load the class using the agent class loader theClass = findClass(className, loader); @@ -547,7 +547,7 @@ public class MBeanInstantiator { throws ReflectionException, MBeanException { - Class theClass = findClassWithDefaultLoaderRepository(className); + Class theClass = findClassWithDefaultLoaderRepository(className); return instantiate(theClass, params, signature, loader); } @@ -595,7 +595,7 @@ public class MBeanInstantiator { // ------------------------------ // ------------------------------ - Class theClass; + Class theClass; if (loaderName == null) { theClass = findClass(className, loader); @@ -617,10 +617,10 @@ public class MBeanInstantiator { * Load a class with the specified loader, or with this object * class loader if the specified loader is null. **/ - static Class loadClass(String className, ClassLoader loader) + static Class loadClass(String className, ClassLoader loader) throws ReflectionException { - Class theClass; + Class theClass; if (className == null) { throw new RuntimeOperationsException(new IllegalArgumentException("The class name cannot be null"), @@ -647,15 +647,15 @@ public class MBeanInstantiator { * Load the classes specified in the signature with the given loader, * or with this object class loader. **/ - static Class[] loadSignatureClasses(String signature[], - ClassLoader loader) + static Class[] loadSignatureClasses(String signature[], + ClassLoader loader) throws ReflectionException { if (signature == null) return null; final ClassLoader aLoader = (loader==null?MBeanInstantiator.class.getClassLoader():loader); final int length= signature.length; - final Class tab[]=new Class[length]; + final Class tab[]=new Class[length]; if (length == 0) return tab; try { @@ -664,7 +664,7 @@ public class MBeanInstantiator { // forth) // - final Class primCla = primitiveClasses.get(signature[i]); + final Class primCla = primitiveClasses.get(signature[i]); if (primCla != null) { tab[i] = primCla; continue; @@ -710,9 +710,9 @@ public class MBeanInstantiator { private static final Map> primitiveClasses = Util.newMap(); static { - for (Class c : new Class[] {byte.class, short.class, int.class, - long.class, float.class, double.class, - char.class, boolean.class}) + for (Class c : new Class[] {byte.class, short.class, int.class, + long.class, float.class, double.class, + char.class, boolean.class}) primitiveClasses.put(c.getName(), c); } } diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java index 6479f9751e0..af5420c38f3 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java @@ -160,7 +160,7 @@ class MXBeanIntrospector extends MBeanIntrospector { // matched to the corresponding Java type, except when that // type is primitive. Type t = m.getGenericParameterTypes()[paramNo]; - return (!(t instanceof Class) || !((Class) t).isPrimitive()); + return (!(t instanceof Class) || !((Class) t).isPrimitive()); } else { Object v; try { @@ -354,7 +354,7 @@ class MXBeanIntrospector extends MBeanIntrospector { } } - private static Descriptor typeDescriptor(OpenType openType, + private static Descriptor typeDescriptor(OpenType openType, Type originalType) { return new ImmutableDescriptor( new String[] {"openType", @@ -380,37 +380,37 @@ class MXBeanIntrospector extends MBeanIntrospector { if (type instanceof GenericArrayType) { return canUseOpenInfo( ((GenericArrayType) type).getGenericComponentType()); - } else if (type instanceof Class && ((Class) type).isArray()) { + } else if (type instanceof Class && ((Class) type).isArray()) { return canUseOpenInfo( ((Class) type).getComponentType()); } - return (!(type instanceof Class && ((Class) type).isPrimitive())); + return (!(type instanceof Class && ((Class) type).isPrimitive())); } private static String originalTypeString(Type type) { - if (type instanceof Class) - return ((Class) type).getName(); + if (type instanceof Class) + return ((Class) type).getName(); else - return genericTypeString(type); + return typeName(type); } - private static String genericTypeString(Type type) { + static String typeName(Type type) { if (type instanceof Class) { Class c = (Class) type; if (c.isArray()) - return genericTypeString(c.getComponentType()) + "[]"; + return typeName(c.getComponentType()) + "[]"; else return c.getName(); } else if (type instanceof GenericArrayType) { GenericArrayType gat = (GenericArrayType) type; - return genericTypeString(gat.getGenericComponentType()) + "[]"; + return typeName(gat.getGenericComponentType()) + "[]"; } else if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; StringBuilder sb = new StringBuilder(); - sb.append(genericTypeString(pt.getRawType())).append("<"); + sb.append(typeName(pt.getRawType())).append("<"); String sep = ""; for (Type t : pt.getActualTypeArguments()) { - sb.append(sep).append(genericTypeString(t)); + sb.append(sep).append(typeName(t)); sep = ", "; } return sb.append(">").toString(); diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java index 2c74e5890c0..cbdce77a71e 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java @@ -54,7 +54,8 @@ class ObjectInputStreamWithLoader extends ObjectInputStream { this.loader = theLoader; } - protected Class resolveClass(ObjectStreamClass aClass) + @Override + protected Class resolveClass(ObjectStreamClass aClass) throws IOException, ClassNotFoundException { if (loader == null) { return super.resolveClass(aClass); diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java index 0576f80ebed..b078bac8f57 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java @@ -47,16 +47,16 @@ final class SecureClassLoaderRepository public SecureClassLoaderRepository(ClassLoaderRepository clr) { this.clr=clr; } - public final Class loadClass(String className) + public final Class loadClass(String className) throws ClassNotFoundException { return clr.loadClass(className); } - public final Class loadClassWithout(ClassLoader loader, + public final Class loadClassWithout(ClassLoader loader, String className) throws ClassNotFoundException { return clr.loadClassWithout(loader,className); } - public final Class loadClassBefore(ClassLoader loader, + public final Class loadClassBefore(ClassLoader loader, String className) throws ClassNotFoundException { return clr.loadClassBefore(loader,className); diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java index 6307adbf8d9..5fe4d1542cc 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java @@ -669,7 +669,7 @@ public class Util { } public static Set cloneSet(Set set) { - if (set instanceof SortedSet) { + if (set instanceof SortedSet) { @SuppressWarnings("unchecked") SortedSet sset = (SortedSet) set; set = new TreeSet(sset.comparator()); @@ -680,7 +680,7 @@ public class Util { } public static Set equivalentEmptySet(Set set) { - if (set instanceof SortedSet) { + if (set instanceof SortedSet) { @SuppressWarnings("unchecked") SortedSet sset = (SortedSet) set; set = new TreeSet(sset.comparator()); diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java index b6662937f93..6f8ed6e9474 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java @@ -118,9 +118,9 @@ class WeakIdentityHashMap { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof IdentityWeakReference)) + if (!(o instanceof IdentityWeakReference)) return false; - IdentityWeakReference wr = (IdentityWeakReference) o; + IdentityWeakReference wr = (IdentityWeakReference) o; Object got = get(); return (got != null && got == wr.get()); } diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java index 234f50f22da..cd4de2aae10 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java @@ -120,7 +120,7 @@ public class ArrayNotificationBuffer implements NotificationBuffer { private final Collection sharers = new HashSet(1); public static NotificationBuffer getNotificationBuffer( - MBeanServer mbs, Map env) { + MBeanServer mbs, Map env) { if (env == null) env = Collections.emptyMap(); diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java index ab6bd60caf8..cb94371fdc9 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java @@ -54,7 +54,7 @@ import com.sun.jmx.remote.util.EnvHelp; public abstract class ClientNotifForwarder { - public ClientNotifForwarder(Map env) { + public ClientNotifForwarder(Map env) { this(null, env); } @@ -113,7 +113,7 @@ public abstract class ClientNotifForwarder { private Thread thread; } - public ClientNotifForwarder(ClassLoader defaultClassLoader, Map env) { + public ClientNotifForwarder(ClassLoader defaultClassLoader, Map env) { maxNotifications = EnvHelp.getMaxFetchNotifNumber(env); timeout = EnvHelp.getFetchTimeout(env); diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java index 8d57b8f92a6..b610828065a 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java @@ -36,7 +36,7 @@ import org.omg.CORBA.ORB; import org.omg.CORBA.TypeCode; import org.omg.CORBA.portable.BoxedValueHelper; -@SuppressWarnings("deprecation") +@SuppressWarnings({"deprecation", "rawtypes"}) public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream { public ProxyInputStream(org.omg.CORBA.portable.InputStream in) { this.in = in; diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java index c3542cc1d8a..dab9b872d64 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java @@ -59,7 +59,7 @@ public class ServerNotifForwarder { public ServerNotifForwarder(MBeanServer mbeanServer, - Map env, + Map env, NotificationBuffer notifBuffer, String connectionId) { this.mbeanServer = mbeanServer; diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java index 64c00b0174b..614edd464fb 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java @@ -29,6 +29,6 @@ import java.io.IOException; import java.rmi.MarshalledObject; public interface Unmarshal { - public Object get(MarshalledObject mo) + public Object get(MarshalledObject mo) throws IOException, ClassNotFoundException; } diff --git a/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java b/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java index a901a19c8f8..33cd6b4ce7c 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java @@ -26,6 +26,7 @@ package com.sun.jmx.remote.security; import com.sun.jmx.mbeanserver.GetPropertyAction; +import com.sun.jmx.mbeanserver.Util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -146,8 +147,8 @@ public class FileLoginModule implements LoginModule { // Initial state private Subject subject; private CallbackHandler callbackHandler; - private Map sharedState; - private Map options; + private Map sharedState; + private Map options; private String passwordFile; private String passwordFileDisplayName; private boolean userSuppliedPasswordFile; @@ -172,7 +173,7 @@ public class FileLoginModule implements LoginModule { this.subject = subject; this.callbackHandler = callbackHandler; - this.sharedState = sharedState; + this.sharedState = Util.cast(sharedState); this.options = options; // initialize any configured options @@ -454,8 +455,8 @@ public class FileLoginModule implements LoginModule { if (storePass && !sharedState.containsKey(USERNAME_KEY) && !sharedState.containsKey(PASSWORD_KEY)) { - ((Map) sharedState).put(USERNAME_KEY, username); - ((Map) sharedState).put(PASSWORD_KEY, password); + sharedState.put(USERNAME_KEY, username); + sharedState.put(PASSWORD_KEY, password); } // Create a new user principal diff --git a/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java b/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java index 631ee3e3b7b..70c72eaf9ef 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java @@ -87,7 +87,7 @@ public final class JMXPluggableAuthenticator implements JMXAuthenticator { * @exception SecurityException if the authentication mechanism cannot be * initialized. */ - public JMXPluggableAuthenticator(Map env) { + public JMXPluggableAuthenticator(Map env) { String loginConfigName = null; String passwordFile = null; diff --git a/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java b/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java index 2e90b11bf4b..66c78f2775e 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java @@ -249,9 +249,8 @@ public class MBeanServerFileAccessController } }); if (s == null) return; /* security has not been enabled */ - final Set principals = s.getPrincipals(); - for (Iterator i = principals.iterator(); i.hasNext(); ) { - final Principal p = (Principal) i.next(); + final Set principals = s.getPrincipals(); + for (Principal p : principals) { String grantedAccessLevel; synchronized (props) { grantedAccessLevel = props.getProperty(p.getName()); @@ -271,8 +270,8 @@ public class MBeanServerFileAccessController } private void checkValues(Properties props) { - Collection c = props.values(); - for (Iterator i = c.iterator(); i.hasNext(); ) { + Collection c = props.values(); + for (Iterator i = c.iterator(); i.hasNext(); ) { final String accessLevel = (String) i.next(); if (!accessLevel.equals(READONLY) && !accessLevel.equals(READWRITE)) { diff --git a/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java b/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java index dfbabeb4184..f59f3265f4e 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java @@ -38,7 +38,7 @@ public class ClassLoaderWithRepository extends ClassLoader { this.cl2 = cl2; } - protected Class findClass(String name) throws ClassNotFoundException { + protected Class findClass(String name) throws ClassNotFoundException { try { return repository.loadClass(name); } catch (ClassNotFoundException cne) { diff --git a/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java b/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java index c3a1c451af6..2cd6a02e1ba 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java @@ -41,7 +41,7 @@ public class ClassLogger { people to use at least J2SE 1.4. */ boolean loaded = false; try { - Class c = java.util.logging.Logger.class; + Class c = java.util.logging.Logger.class; loaded = true; } catch (Error e) { // OK. diff --git a/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java b/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java index 67b9ea59561..c86df1c88ee 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java @@ -117,7 +117,7 @@ public class EnvHelp { * jmx.remote.default.class.loader.name is specified * and the ClassLoader MBean is not found in mbs. */ - public static ClassLoader resolveServerClassLoader(Map env, + public static ClassLoader resolveServerClassLoader(Map env, MBeanServer mbs) throws InstanceNotFoundException { @@ -194,7 +194,7 @@ public class EnvHelp { * jmx.remote.default.class.loader is specified * and is not an instance of {@link ClassLoader}. */ - public static ClassLoader resolveClientClassLoader(Map env) { + public static ClassLoader resolveClientClassLoader(Map env) { if (env == null) return Thread.currentThread().getContextClassLoader(); @@ -241,7 +241,7 @@ public class EnvHelp { try { java.lang.reflect.Method getCause = - t.getClass().getMethod("getCause", (Class[]) null); + t.getClass().getMethod("getCause", (Class[]) null); ret = (Throwable)getCause.invoke(t, (Object[]) null); } catch (Exception e) { @@ -264,7 +264,7 @@ public class EnvHelp { * Returns the size of a notification buffer for a connector server. * The default value is 1000. */ - public static int getNotifBufferSize(Map env) { + public static int getNotifBufferSize(Map env) { int defaultQueueSize = 1000; // default value // keep it for the compability for the fix: @@ -327,7 +327,7 @@ public class EnvHelp { * Returns the maximum notification number which a client will * fetch every time. */ - public static int getMaxFetchNotifNumber(Map env) { + public static int getMaxFetchNotifNumber(Map env) { return (int) getIntegerAttribute(env, MAX_FETCH_NOTIFS, 1000, 1, Integer.MAX_VALUE); } @@ -344,7 +344,7 @@ public class EnvHelp { /** * Returns the timeout for a client to fetch notifications. */ - public static long getFetchTimeout(Map env) { + public static long getFetchTimeout(Map env) { return getIntegerAttribute(env, FETCH_TIMEOUT, 60000L, 0, Long.MAX_VALUE); } @@ -361,7 +361,7 @@ public class EnvHelp { "com.sun.jmx.remote.notification.access.controller"; public static NotificationAccessController getNotificationAccessController( - Map env) { + Map env) { return (env == null) ? null : (NotificationAccessController) env.get(NOTIF_ACCESS_CONTROLLER); } @@ -378,7 +378,7 @@ public class EnvHelp { * an entry for name but it does not meet the * constraints above. */ - public static long getIntegerAttribute(Map env, String name, + public static long getIntegerAttribute(Map env, String name, long defaultValue, long minValue, long maxValue) { final Object o; @@ -421,9 +421,8 @@ public class EnvHelp { /* Check that all attributes have a key that is a String. Could make further checks, e.g. appropriate types for attributes. */ - public static void checkAttributes(Map attributes) { - for (Iterator it = attributes.keySet().iterator(); it.hasNext(); ) { - Object key = it.next(); + public static void checkAttributes(Map attributes) { + for (Object key : attributes.keySet()) { if (!(key instanceof String)) { final String msg = "Attributes contain key that is not a string: " + key; @@ -455,7 +454,7 @@ public class EnvHelp { logger.trace("purgeUnserializable", "starts"); ObjectOutputStream oos = null; int i = 0; - for (Iterator it = objects.iterator(); it.hasNext(); i++) { + for (Iterator it = objects.iterator(); it.hasNext(); i++) { Object v = it.next(); if (v == null || v instanceof String) { @@ -564,18 +563,18 @@ public class EnvHelp { guarantees that we will never call next() on the corresponding iterator. */ String sentinelKey = map.lastKey() + "X"; - Iterator keyIterator = map.keySet().iterator(); - Iterator stringIterator = hiddenStrings.iterator(); - Iterator prefixIterator = hiddenPrefixes.iterator(); + Iterator keyIterator = map.keySet().iterator(); + Iterator stringIterator = hiddenStrings.iterator(); + Iterator prefixIterator = hiddenPrefixes.iterator(); String nextString; if (stringIterator.hasNext()) - nextString = (String) stringIterator.next(); + nextString = stringIterator.next(); else nextString = sentinelKey; String nextPrefix; if (prefixIterator.hasNext()) - nextPrefix = (String) prefixIterator.next(); + nextPrefix = prefixIterator.next(); else nextPrefix = sentinelKey; @@ -583,7 +582,7 @@ public class EnvHelp { or prefix, remove it. */ keys: while (keyIterator.hasNext()) { - String key = (String) keyIterator.next(); + String key = keyIterator.next(); /* Continue through string-match values until we find one that is either greater than the current key, or equal @@ -591,7 +590,7 @@ public class EnvHelp { int cmp = +1; while ((cmp = nextString.compareTo(key)) < 0) { if (stringIterator.hasNext()) - nextString = (String) stringIterator.next(); + nextString = stringIterator.next(); else nextString = sentinelKey; } @@ -609,7 +608,7 @@ public class EnvHelp { continue keys; } if (prefixIterator.hasNext()) - nextPrefix = (String) prefixIterator.next(); + nextPrefix = prefixIterator.next(); else nextPrefix = sentinelKey; } @@ -640,7 +639,7 @@ public class EnvHelp { /** * Returns the server side connection timeout. */ - public static long getServerConnectionTimeout(Map env) { + public static long getServerConnectionTimeout(Map env) { return getIntegerAttribute(env, SERVER_CONNECTION_TIMEOUT, 120000L, 0, Long.MAX_VALUE); } @@ -656,7 +655,7 @@ public class EnvHelp { /** * Returns the client connection check period. */ - public static long getConnectionCheckPeriod(Map env) { + public static long getConnectionCheckPeriod(Map env) { return getIntegerAttribute(env, CLIENT_CONNECTION_CHECK_PERIOD, 60000L, 0, Long.MAX_VALUE); } @@ -691,7 +690,7 @@ public class EnvHelp { * to {@code String}. */ public static boolean computeBooleanFromString( - Map env, String prop, boolean systemProperty) { + Map env, String prop, boolean systemProperty) { if (env == null) throw new IllegalArgumentException("env map cannot be null"); @@ -744,7 +743,8 @@ public class EnvHelp { * to {@code String}. */ public static boolean computeBooleanFromString( - Map env, String prop, boolean systemProperty, boolean defaultValue) { + Map env, String prop, + boolean systemProperty, boolean defaultValue) { if (env == null) throw new IllegalArgumentException("env map cannot be null"); @@ -774,7 +774,7 @@ public class EnvHelp { public static Hashtable mapToHashtable(Map map) { HashMap m = new HashMap(map); if (m.containsKey(null)) m.remove(null); - for (Iterator i = m.values().iterator(); i.hasNext(); ) + for (Iterator i = m.values().iterator(); i.hasNext(); ) if (i.next() == null) i.remove(); return new Hashtable(m); } @@ -783,7 +783,7 @@ public class EnvHelp { * Returns true if the parameter JMXConnector.USE_EVENT_SERVICE is set to a * String equals "true" by ignoring case in the map or in the System. */ - public static boolean eventServiceEnabled(Map env) { + public static boolean eventServiceEnabled(Map env) { return computeBooleanFromString(env, JMXConnector.USE_EVENT_SERVICE, true); } @@ -793,7 +793,7 @@ public class EnvHelp { * If the property DELEGATE_TO_EVENT_SERVICE is not set, returns * a default value of "true". */ - public static boolean delegateToEventService(Map env) { + public static boolean delegateToEventService(Map env) { return computeBooleanFromString(env, JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE, true, true); } diff --git a/jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java b/jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java index 6281b68a574..b660898731a 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java @@ -138,8 +138,8 @@ public class EventClientConnection implements InvocationHandler, Class interfaceClass, Callable eventClientFactory) { final InvocationHandler handler = new EventClientConnection(connection,eventClientFactory); - final Class[] interfaces = - new Class[] {interfaceClass, EventClientFactory.class}; + final Class[] interfaces = + new Class[] {interfaceClass, EventClientFactory.class}; Object proxy = Proxy.newProxyInstance(interfaceClass.getClassLoader(), @@ -156,7 +156,7 @@ public class EventClientConnection implements InvocationHandler, // add/remove notification listener are routed to the EventClient if (methodName.equals("addNotificationListener") || methodName.equals("removeNotificationListener")) { - final Class[] sig = method.getParameterTypes(); + final Class[] sig = method.getParameterTypes(); if (sig.length>1 && NotificationListener.class.isAssignableFrom(sig[1])) { return invokeBroadcasterMethod(proxy,method,args); @@ -164,7 +164,7 @@ public class EventClientConnection implements InvocationHandler, } // subscribe/unsubscribe are also routed to the EventClient. - final Class clazz = method.getDeclaringClass(); + final Class clazz = method.getDeclaringClass(); if (clazz.equals(EventClientFactory.class)) { return invokeEventClientSubscriberMethod(proxy,method,args); } @@ -319,7 +319,7 @@ public class EventClientConnection implements InvocationHandler, return true; if (methodName.equals("equals") && Arrays.equals(method.getParameterTypes(), - new Class[] {Object.class}) + new Class[] {Object.class}) && isLocal(proxy, method)) return true; return false; diff --git a/jdk/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java b/jdk/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java index b54a23b2bb1..041736310c1 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java @@ -32,7 +32,7 @@ public class OrderClassLoaders extends ClassLoader { this.cl2 = cl2; } - protected Class findClass(String name) throws ClassNotFoundException { + protected Class findClass(String name) throws ClassNotFoundException { try { return super.findClass(name); } catch (ClassNotFoundException cne) { diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java index d7565157e49..da5c4960973 100644 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java +++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java @@ -70,10 +70,13 @@ public class IdResolver { */ public static void registerElementById(Element element, String idValue) { Document doc = element.getOwnerDocument(); - WeakHashMap elementMap = (WeakHashMap) docMap.get(doc); - if(elementMap == null) { - elementMap = new WeakHashMap(); - docMap.put(doc, elementMap); + WeakHashMap elementMap; + synchronized (docMap) { + elementMap = (WeakHashMap) docMap.get(doc); + if (elementMap == null) { + elementMap = new WeakHashMap(); + docMap.put(doc, elementMap); + } } elementMap.put(idValue, new WeakReference(element)); } @@ -153,7 +156,10 @@ public class IdResolver { private static Element getElementByIdType(Document doc, String id) { if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "getElementByIdType() Search for ID " + id); - WeakHashMap elementMap = (WeakHashMap) docMap.get(doc); + WeakHashMap elementMap; + synchronized (docMap) { + elementMap = (WeakHashMap) docMap.get(doc); + } if (elementMap != null) { WeakReference weakReference = (WeakReference) elementMap.get(id); if (weakReference != null) { diff --git a/jdk/src/share/classes/javax/management/AttributeList.java b/jdk/src/share/classes/javax/management/AttributeList.java index b385c3c0f79..1ce3004a337 100644 --- a/jdk/src/share/classes/javax/management/AttributeList.java +++ b/jdk/src/share/classes/javax/management/AttributeList.java @@ -159,7 +159,7 @@ public class AttributeList extends ArrayList { checkTypeSafe(this); typeSafe = true; } - return (List) (List) this; + return (List) (List) this; } /** diff --git a/jdk/src/share/classes/javax/management/DefaultLoaderRepository.java b/jdk/src/share/classes/javax/management/DefaultLoaderRepository.java index 6cf16435ad6..85028b44c50 100644 --- a/jdk/src/share/classes/javax/management/DefaultLoaderRepository.java +++ b/jdk/src/share/classes/javax/management/DefaultLoaderRepository.java @@ -62,7 +62,7 @@ public class DefaultLoaderRepository { * * @exception ClassNotFoundException The specified class could not be found. */ - public static Class loadClass(String className) + public static Class loadClass(String className) throws ClassNotFoundException { return javax.management.loading.DefaultLoaderRepository.loadClass(className); } @@ -82,7 +82,7 @@ public class DefaultLoaderRepository { * * @exception ClassNotFoundException The specified class could not be found. */ - public static Class loadClassWithout(ClassLoader loader,String className) + public static Class loadClassWithout(ClassLoader loader,String className) throws ClassNotFoundException { return javax.management.loading.DefaultLoaderRepository.loadClassWithout(loader, className); } diff --git a/jdk/src/share/classes/javax/management/Descriptor.java b/jdk/src/share/classes/javax/management/Descriptor.java index 70c17f2eedb..a74fb11cde7 100644 --- a/jdk/src/share/classes/javax/management/Descriptor.java +++ b/jdk/src/share/classes/javax/management/Descriptor.java @@ -101,7 +101,7 @@ import javax.management.openmbean.OpenType; * * NameTypeUsed inMeaning * - * defaultValueObject + * defaultValueObject * MBeanAttributeInfo
MBeanParameterInfo * * Default value for an attribute or parameter. See @@ -144,7 +144,7 @@ import javax.management.openmbean.OpenType; * might be disabled if it cannot currently be emitted but could be in * other circumstances. * - * immutableInfoString + * immutableInfoString * MBeanInfo * * The string {@code "true"} or {@code "false"} according as this @@ -153,20 +153,24 @@ import javax.management.openmbean.OpenType; * the lifetime of the MBean. Hence, a client can read it once and * cache the read value. When this field is false or absent, there is * no such guarantee, although that does not mean that the MBeanInfo - * will necessarily change. + * will necessarily change. See also the {@code "jmx.mbean.info.changed"} + * notification. * * infoTimeoutString
LongMBeanInfo * - * The time in milli-seconds that the MBeanInfo can reasonably be - * expected to be unchanged. The value can be a {@code Long} or a - * decimal string. This provides a hint from a DynamicMBean or any + * The time in milli-seconds that the MBeanInfo can + * reasonably be expected to be unchanged. The value can be a {@code Long} + * or a decimal string. This provides a hint from a DynamicMBean or any * MBean that does not define {@code immutableInfo} as {@code true} * that the MBeanInfo is not likely to change within this period and * therefore can be cached. When this field is missing or has the * value zero, it is not recommended to cache the MBeanInfo unless it - * has the {@code immutableInfo} set to {@code true}. + * has the {@code immutableInfo} set to {@code true} or it has {@code "jmx.mbean.info.changed"} in + * its {@link MBeanNotificationInfo} array. * - * interfaceClassName + * interfaceClassName * StringMBeanInfo * * The Java interface name for a Standard MBean or MXBean, as @@ -175,19 +179,19 @@ import javax.management.openmbean.OpenType; * StandardMBean} class will have this field in its MBeanInfo * Descriptor. * - * legalValues + * legalValues * {@literal Set}MBeanAttributeInfo
MBeanParameterInfo * * Legal values for an attribute or parameter. See * {@link javax.management.openmbean}. * - * maxValueObject + * maxValueObject * MBeanAttributeInfo
MBeanParameterInfo * * Maximum legal value for an attribute or parameter. See * {@link javax.management.openmbean}. * - * metricTypeString + * metricTypeString * MBeanAttributeInfo
MBeanOperationInfo * * The type of a metric, one of the strings "counter" or "gauge". @@ -200,13 +204,13 @@ import javax.management.openmbean.OpenType; * that can increase or decrease. Examples might be the number of * open connections or a cache hit rate or a temperature reading. * - * minValueObject + * minValueObject * MBeanAttributeInfo
MBeanParameterInfo * * Minimum legal value for an attribute or parameter. See * {@link javax.management.openmbean}. * - * mxbeanString + * mxbeanString * MBeanInfo * * The string {@code "true"} or {@code "false"} according as this @@ -223,7 +227,7 @@ import javax.management.openmbean.OpenType; * MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default} * one. * - * openType{@link OpenType} + * openType{@link OpenType} * MBeanAttributeInfo
MBeanOperationInfo
MBeanParameterInfo * *

The Open Type of this element. In the case of {@code @@ -240,7 +244,7 @@ import javax.management.openmbean.OpenType; * which case it indicates the Open Type that the {@link * Notification#getUserData() user data} will have. * - * originalTypeString + * originalTypeString * MBeanAttributeInfo
MBeanOperationInfo
MBeanParameterInfo * *

The original Java type of this element as it appeared in the @@ -282,11 +286,132 @@ import javax.management.openmbean.OpenType; * * * - *

Some additional fields are defined by Model MBeans. See - * {@link javax.management.modelmbean.ModelMBeanInfo ModelMBeanInfo} - * and related classes and the chapter "Model MBeans" of the - * - * JMX Specification.

+ *

Some additional fields are defined by Model MBeans. See the + * information for {@code ModelMBeanInfo}, + * {@code ModelMBeanAttributeInfo}, + * {@code ModelMBeanConstructorInfo}, + * {@code ModelMBeanNotificationInfo}, and + * {@code ModelMBeanOperationInfo}, as + * well as the chapter "Model MBeans" of the JMX + * Specification. The following table summarizes these fields. Note + * that when the Type in this table is Number, a String that is the decimal + * representation of a Long can also be used.

+ * + *

Nothing prevents the use of these fields in MBeans that are not Model + * MBeans. The displayName, severity, and visibility fields are of + * interest outside Model MBeans, for example. But only Model MBeans have + * a predefined behavior for these fields.

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
NameTypeUsed inMeaning
classStringModelMBeanOperationInfoClass where method is defined (fully qualified).
currencyTimeLimitNumberModelMBeanInfo
ModelMBeanAttributeInfo
ModelMBeanOperationInfo
How long cached value is valid: <0 never, =0 always, + * >0 seconds.
defaultObjectModelMBeanAttributeInfoDefault value for attribute.
descriptorTypeStringAnyType of descriptor, "mbean", "attribute", "constructor", "operation", + * or "notification".
displayNameStringAnyHuman readable name of this item.
exportStringModelMBeanInfoName to be used to export/expose this MBean so that it is + * findable by other JMX Agents.
getMethodStringModelMBeanAttributeInfoName of operation descriptor for get method.
lastUpdatedTimeStampNumberModelMBeanAttributeInfo
ModelMBeanOperationInfo
When value was set.
logStringModelMBeanInfo
ModelMBeanNotificationInfo
t or T: log all notifications, f or F: log no notifications.
logFileStringModelMBeanInfo
ModelMBeanNotificationInfo
Fully qualified filename to log events to.
messageIDStringModelMBeanNotificationInfoUnique key for message text (to allow translation, analysis).
messageTextStringModelMBeanNotificationInfoText of notification.
nameStringAnyName of this item.
persistFileStringModelMBeanInfoFile name into which the MBean should be persisted.
persistLocationStringModelMBeanInfoThe fully qualified directory name where the MBean should be + * persisted (if appropriate).
persistPeriodNumberModelMBeanInfo
ModelMBeanAttributeInfo
Frequency of persist cycle in seconds. Used when persistPolicy is + * "OnTimer" or "NoMoreOftenThan".
persistPolicyStringModelMBeanInfo
ModelMBeanAttributeInfo
One of: OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never. + * See the section "MBean Descriptor Fields" in the JMX specification + * document.
presentationStringStringAnyXML formatted string to allow presentation of data.
protocolMapDescriptorModelMBeanAttributeInfoSee the section "Protocol Map Support" in the JMX specification + * document. Mappings must be appropriate for the attribute and entries + * can be updated or augmented at runtime.
roleStringModelMBeanConstructorInfo
ModelMBeanOperationInfo
One of "constructor", "operation", "getter", or "setter".
setMethodStringModelMBeanAttributeInfoName of operation descriptor for set method.
severityNumberModelMBeanNotificationInfo0-6 where 0: unknown; 1: non-recoverable; + * 2: critical, failure; 3: major, severe; + * 4: minor, marginal, error; 5: warning; + * 6: normal, cleared, informative
targetObjectObjectModelMBeanOperationInfoObject on which to execute this method.
targetTypeStringModelMBeanOperationInfotype of object reference for targetObject. Can be: + * ObjectReference | Handle | EJBHandle | IOR | RMIReference.
valueObjectModelMBeanAttributeInfo
ModelMBeanOperationInfo
Current (cached) value for attribute or operation.
visibilityNumberAny1-4 where 1: always visible, 4: rarely visible.
* * @since 1.5 */ @@ -439,7 +564,7 @@ public interface Descriptor extends Serializable, Cloneable public boolean isValid() throws RuntimeOperationsException; /** - * Compares this descriptor to the given object. The objects are equal if + *

Compares this descriptor to the given object. The objects are equal if * the given object is also a Descriptor, and if the two Descriptors have * the same field names (possibly differing in case) and the same * associated values. The respective values for a field in the two diff --git a/jdk/src/share/classes/javax/management/JMRuntimeException.java b/jdk/src/share/classes/javax/management/JMRuntimeException.java index c27ec1a561b..70998c8a2d8 100644 --- a/jdk/src/share/classes/javax/management/JMRuntimeException.java +++ b/jdk/src/share/classes/javax/management/JMRuntimeException.java @@ -70,7 +70,7 @@ public class JMRuntimeException extends RuntimeException { try { java.lang.reflect.Method initCause = Throwable.class.getMethod("initCause", - new Class[] {Throwable.class}); + new Class[] {Throwable.class}); initCause.invoke(this, new Object[] {cause}); } catch (Exception e) { // OK: just means we won't have debugging info diff --git a/jdk/src/share/classes/javax/management/JMX.java b/jdk/src/share/classes/javax/management/JMX.java index 87c7dd227ce..ac7468d07dd 100644 --- a/jdk/src/share/classes/javax/management/JMX.java +++ b/jdk/src/share/classes/javax/management/JMX.java @@ -463,6 +463,12 @@ public class JMX { * likewise for the other methods of {@link * NotificationBroadcaster} and {@link NotificationEmitter}.

* + *

This method is equivalent to {@link + * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions) + * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where + * {@code opts} is a {@link JMX.ProxyOptions} representing the + * {@code notificationEmitter} parameter.

+ * * @param connection the MBean server to forward to. * @param objectName the name of the MBean within * {@code connection} to forward to. @@ -555,10 +561,6 @@ public class JMX { * * * - *

The object returned by this method is a - * {@link Proxy} whose {@code InvocationHandler} is an - * {@link MBeanServerInvocationHandler}.

- * *

This method is equivalent to {@link * #newMXBeanProxy(MBeanServerConnection, ObjectName, Class, * boolean) newMXBeanProxy(connection, objectName, interfaceClass, @@ -601,6 +603,17 @@ public class JMX { * likewise for the other methods of {@link * NotificationBroadcaster} and {@link NotificationEmitter}.

* + *

This method is equivalent to {@link + * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions) + * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where + * {@code opts} is a {@link JMX.ProxyOptions} where the {@link + * JMX.ProxyOptions#getMXBeanMappingFactory() MXBeanMappingFactory} + * property is + * {@link MXBeanMappingFactory#forInterface(Class) + * MXBeanMappingFactory.forInterface(interfaceClass)} and the {@link + * JMX.ProxyOptions#isNotificationEmitter() notificationEmitter} property + * is equal to the {@code notificationEmitter} parameter.

+ * * @param connection the MBean server to forward to. * @param objectName the name of the MBean within * {@code connection} to forward to. @@ -655,6 +668,36 @@ public class JMX { * arbitrary Java types and Open Types. * * + *

The object returned by this method is a + * {@link Proxy} whose {@code InvocationHandler} is an + * {@link MBeanServerInvocationHandler}. This means that it is possible + * to retrieve the parameters that were used to produce the proxy. If the + * proxy was produced as follows...

+ * + *
+     * FooMBean proxy =
+     *     JMX.newMBeanProxy(connection, objectName, FooMBean.class, opts);
+     * 
+ * + *

...then you can get the {@code MBeanServerInvocationHandler} like + * this...

+ * + *
+     * MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
+     *     {@link Proxy#getInvocationHandler(Object)
+     *            Proxy.getInvocationHandler}(proxy);
+     * 
+ * + *

...and you can retrieve {@code connection}, {@code + * objectName}, and {@code opts} using the {@link + * MBeanServerInvocationHandler#getMBeanServerConnection() + * getMBeanServerConnection()}, {@link + * MBeanServerInvocationHandler#getObjectName() getObjectName()}, and + * {@link MBeanServerInvocationHandler#getMBeanOptions() getMBeanOptions()} + * methods on {@code mbsih}. You can retrieve {@code FooMBean.class} + * using {@code proxy.getClass().}{@link + * Class#getInterfaces() getInterfaces()}.

+ * * @param connection the MBean server to forward to. * @param objectName the name of the MBean within * {@code connection} to forward to. @@ -703,12 +746,12 @@ public class JMX { InvocationHandler handler = new MBeanServerInvocationHandler( connection, objectName, opts); - final Class[] interfaces; + final Class[] interfaces; if (notificationEmitter) { interfaces = new Class[] {interfaceClass, NotificationEmitter.class}; } else - interfaces = new Class[] {interfaceClass}; + interfaces = new Class[] {interfaceClass}; Object proxy = Proxy.newProxyInstance( interfaceClass.getClassLoader(), interfaces, diff --git a/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java b/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java index 5b41bb4b63c..2566c3e48a2 100644 --- a/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java @@ -316,7 +316,7 @@ public class MBeanAttributeInfo extends MBeanFeatureInfo implements Cloneable { */ private static String attributeType(Method getter, Method setter) throws IntrospectionException { - Class type = null; + Class type = null; if (getter != null) { if (getter.getParameterTypes().length != 0) { @@ -330,7 +330,7 @@ public class MBeanAttributeInfo extends MBeanFeatureInfo implements Cloneable { } if (setter != null) { - Class params[] = setter.getParameterTypes(); + Class params[] = setter.getParameterTypes(); if (params.length != 1) { throw new IntrospectionException("bad setter arg count"); } diff --git a/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java b/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java index f66502e2f06..872c723e3af 100644 --- a/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java @@ -64,7 +64,7 @@ public class MBeanConstructorInfo extends MBeanFeatureInfo implements Cloneable * @param constructor The java.lang.reflect.Constructor * object describing the MBean constructor. */ - public MBeanConstructorInfo(String description, Constructor constructor) { + public MBeanConstructorInfo(String description, Constructor constructor) { this(constructor.getName(), description, constructorSignature(constructor), Introspector.descriptorForElement(constructor)); @@ -210,8 +210,8 @@ public class MBeanConstructorInfo extends MBeanFeatureInfo implements Cloneable return hash; } - private static MBeanParameterInfo[] constructorSignature(Constructor cn) { - final Class[] classes = cn.getParameterTypes(); + private static MBeanParameterInfo[] constructorSignature(Constructor cn) { + final Class[] classes = cn.getParameterTypes(); final Annotation[][] annots = cn.getParameterAnnotations(); return MBeanOperationInfo.parameters(classes, annots); } diff --git a/jdk/src/share/classes/javax/management/MBeanInfo.java b/jdk/src/share/classes/javax/management/MBeanInfo.java index 9e30d44a51d..3561e3cfc13 100644 --- a/jdk/src/share/classes/javax/management/MBeanInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanInfo.java @@ -45,6 +45,17 @@ import static javax.management.ImmutableDescriptor.nonNullDescriptor; * management operations. Instances of this class are immutable. * Subclasses may be mutable but this is not recommended.

* + *

Usually the {@code MBeanInfo} for any given MBean does + * not change over the lifetime of that MBean. Dynamic MBeans can change their + * {@code MBeanInfo} and in that case it is recommended that they emit a {@link + * Notification} with a {@linkplain Notification#getType() type} of {@code + * "jmx.mbean.info.changed"} and a {@linkplain Notification#getUserData() + * userData} that is the new {@code MBeanInfo}. This is not required, but + * provides a conventional way for clients of the MBean to discover the change. + * See also the immutableInfo and + * infoTimeout fields in the {@code + * MBeanInfo} {@link Descriptor}.

+ * *

The contents of the MBeanInfo for a Dynamic MBean * are determined by its {@link DynamicMBean#getMBeanInfo * getMBeanInfo()} method. This includes Open MBeans and Model @@ -62,27 +73,49 @@ import static javax.management.ImmutableDescriptor.nonNullDescriptor; * constructors in that object; * *

  • {@link #getAttributes()} returns the list of all attributes - * whose existence is deduced from the presence in the MBean interface - * of a getName, isName, or - * setName method that conforms to the conventions + * whose existence is deduced as follows: + *
      + *
    • if the Standard MBean is defined with an MBean interface, + * from getName, isName, or + * setName methods that conform to the conventions * for Standard MBeans; + *
    • if the Standard MBean is defined with the {@link MBean @MBean} or + * {@link MXBean @MXBean} annotation on a class, from methods with the + * {@link ManagedAttribute @ManagedAttribute} annotation; + *
    * - *
  • {@link #getOperations()} returns the list of all methods in + *
  • {@link #getOperations()} returns the list of all operations whose + * existence is deduced as follows: + *
      + *
    • if the Standard MBean is defined with an MBean interface, from methods in * the MBean interface that do not represent attributes; + *
    • if the Standard MBean is defined with the {@link MBean @MBean} or + * {@link MXBean @MXBean} annotation on a class, from methods with the + * {@link ManagedOperation @ManagedOperation} annotation; + *
    * - *
  • {@link #getNotifications()} returns an empty array if the MBean - * does not implement the {@link NotificationBroadcaster} interface, - * otherwise the result of calling {@link + *
  • {@link #getNotifications()} returns: + *
      + *
    • if the MBean implements the {@link NotificationBroadcaster} interface, + * the result of calling {@link * NotificationBroadcaster#getNotificationInfo()} on it; + *
    • otherwise, if there is a {@link NotificationInfo @NotificationInfo} + * or {@link NotificationInfos @NotificationInfos} annotation on the + * MBean interface or @MBean or @MXBean + * class, the array implied by those annotations; + *
    • otherwise an empty array; + *
    * *
  • {@link #getDescriptor()} returns a descriptor containing the contents - * of any descriptor annotations in the MBean interface. + * of any descriptor annotations in the MBean interface (see + * {@link DescriptorFields @DescriptorFields} and + * {@link DescriptorKey @DescriptorKey}). * * * *

    The description returned by {@link #getDescription()} and the * descriptions of the contained attributes and operations are determined - * by the corresponding Description annotations if any; + * by the corresponding {@link Description} annotations if any; * otherwise their contents are not specified.

    * *

    The remaining details of the MBeanInfo for a @@ -524,8 +557,8 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead { * a WeakHashMap so that we don't prevent a class from being * garbage collected just because we know whether it's immutable. */ - private static final Map arrayGettersSafeMap = - new WeakHashMap(); + private static final Map, Boolean> arrayGettersSafeMap = + new WeakHashMap, Boolean>(); /** * Return true if subclass is known to preserve the @@ -537,7 +570,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead { * This is obviously not an infallible test for immutability, * but it works for the public interfaces of the MBean*Info classes. */ - static boolean arrayGettersSafe(Class subclass, Class immutableClass) { + static boolean arrayGettersSafe(Class subclass, Class immutableClass) { if (subclass == immutableClass) return true; synchronized (arrayGettersSafeMap) { diff --git a/jdk/src/share/classes/javax/management/MBeanOperationInfo.java b/jdk/src/share/classes/javax/management/MBeanOperationInfo.java index e3c26df5265..006fc345d93 100644 --- a/jdk/src/share/classes/javax/management/MBeanOperationInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanOperationInfo.java @@ -308,17 +308,18 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { wrong should be less than the penalty we would pay if it were right and we needlessly hashed in the description and the parameter array. */ + @Override public int hashCode() { return getName().hashCode() ^ getReturnType().hashCode(); } private static MBeanParameterInfo[] methodSignature(Method method) { - final Class[] classes = method.getParameterTypes(); + final Class[] classes = method.getParameterTypes(); final Annotation[][] annots = method.getParameterAnnotations(); return parameters(classes, annots); } - static MBeanParameterInfo[] parameters(Class[] classes, + static MBeanParameterInfo[] parameters(Class[] classes, Annotation[][] annots) { final MBeanParameterInfo[] params = new MBeanParameterInfo[classes.length]; diff --git a/jdk/src/share/classes/javax/management/MBeanServer.java b/jdk/src/share/classes/javax/management/MBeanServer.java index 90d42d2df6c..e6d79e5bd94 100644 --- a/jdk/src/share/classes/javax/management/MBeanServer.java +++ b/jdk/src/share/classes/javax/management/MBeanServer.java @@ -377,19 +377,19 @@ public interface MBeanServer extends MBeanServerConnection { * MBean will not be registered. * @exception RuntimeMBeanException If the postRegister * (MBeanRegistration interface) method of the MBean throws a - * RuntimeException, the registerMBean method will + * RuntimeException, the registerMBean method will * throw a RuntimeMBeanException, although the MBean * registration succeeded. In such a case, the MBean will be actually - * registered even though the registerMBean method + * registered even though the registerMBean method * threw an exception. Note that RuntimeMBeanException can * also be thrown by preRegister, in which case the MBean * will not be registered. * @exception RuntimeErrorException If the postRegister * (MBeanRegistration interface) method of the MBean throws an - * Error, the registerMBean method will + * Error, the registerMBean method will * throw a RuntimeErrorException, although the MBean * registration succeeded. In such a case, the MBean will be actually - * registered even though the registerMBean method + * registered even though the registerMBean method * threw an exception. Note that RuntimeErrorException can * also be thrown by preRegister, in which case the MBean * will not be registered. @@ -411,6 +411,8 @@ public interface MBeanServer extends MBeanServerConnection { * is sent as described above.

    * * @throws RuntimeOperationsException {@inheritDoc} + * @throws RuntimeMBeanException {@inheritDoc} + * @throws RuntimeErrorException {@inheritDoc} */ public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException; diff --git a/jdk/src/share/classes/javax/management/MBeanServerConnection.java b/jdk/src/share/classes/javax/management/MBeanServerConnection.java index 0897684a0b5..16ce58bb883 100644 --- a/jdk/src/share/classes/javax/management/MBeanServerConnection.java +++ b/jdk/src/share/classes/javax/management/MBeanServerConnection.java @@ -76,7 +76,9 @@ public interface MBeanServerConnection extends NotificationManager { * preRegister (MBeanRegistration * interface) method of the MBean has thrown an exception. The * MBean will not be registered. - * @exception RuntimeMBeanException If the postRegister + * @exception RuntimeMBeanException If the MBean's constructor or its + * {@code preRegister} or {@code postRegister} method threw + * a {@code RuntimeException}. If the postRegister * (MBeanRegistration interface) method of the MBean throws a * RuntimeException, the createMBean method will * throw a RuntimeMBeanException, although the MBean creation @@ -148,7 +150,9 @@ public interface MBeanServerConnection extends NotificationManager { * preRegister (MBeanRegistration * interface) method of the MBean has thrown an exception. The * MBean will not be registered. - * @exception RuntimeMBeanException If the postRegister + * @exception RuntimeMBeanException If the MBean's constructor or its + * {@code preRegister} or {@code postRegister} method threw + * a {@code RuntimeException}. If the postRegister * (MBeanRegistration interface) method of the MBean throws a * RuntimeException, the createMBean method will * throw a RuntimeMBeanException, although the MBean creation @@ -223,7 +227,9 @@ public interface MBeanServerConnection extends NotificationManager { * preRegister (MBeanRegistration * interface) method of the MBean has thrown an exception. The * MBean will not be registered. - * @exception RuntimeMBeanException If the postRegister + * @exception RuntimeMBeanException If the MBean's constructor or its + * {@code preRegister} or {@code postRegister} method threw + * a {@code RuntimeException}. If the postRegister * (MBeanRegistration interface) method of the MBean throws a * RuntimeException, the createMBean method will * throw a RuntimeMBeanException, although the MBean creation @@ -295,7 +301,9 @@ public interface MBeanServerConnection extends NotificationManager { * preRegister (MBeanRegistration * interface) method of the MBean has thrown an exception. The * MBean will not be registered. - * @exception RuntimeMBeanException If the postRegister + * @exception RuntimeMBeanException The MBean's constructor or its + * {@code preRegister} or {@code postRegister} method threw + * a {@code RuntimeException}. If the postRegister * (MBeanRegistration interface) method of the MBean throws a * RuntimeException, the createMBean method will * throw a RuntimeMBeanException, although the MBean creation diff --git a/jdk/src/share/classes/javax/management/MBeanServerFactory.java b/jdk/src/share/classes/javax/management/MBeanServerFactory.java index 365f2a7d9b5..e0225200d83 100644 --- a/jdk/src/share/classes/javax/management/MBeanServerFactory.java +++ b/jdk/src/share/classes/javax/management/MBeanServerFactory.java @@ -747,7 +747,7 @@ public class MBeanServerFactory { * Load the builder class through the context class loader. * @param builderClassName The name of the builder class. **/ - private static Class loadBuilderClass(String builderClassName) + private static Class loadBuilderClass(String builderClassName) throws ClassNotFoundException { final ClassLoader loader = Thread.currentThread().getContextClassLoader(); @@ -767,7 +767,7 @@ public class MBeanServerFactory { * If any checked exception needs to be thrown, it is embedded in * a JMRuntimeException. **/ - private static MBeanServerBuilder newBuilder(Class builderClass) { + private static MBeanServerBuilder newBuilder(Class builderClass) { try { final Object abuilder = builderClass.newInstance(); return (MBeanServerBuilder)abuilder; @@ -792,7 +792,7 @@ public class MBeanServerFactory { String builderClassName = AccessController.doPrivileged(act); try { - final Class newBuilderClass; + final Class newBuilderClass; if (builderClassName == null || builderClassName.length() == 0) newBuilderClass = MBeanServerBuilder.class; else @@ -800,7 +800,7 @@ public class MBeanServerFactory { // Check whether a new builder needs to be created if (builder != null) { - final Class builderClass = builder.getClass(); + final Class builderClass = builder.getClass(); if (newBuilderClass == builderClass) return; // no need to create a new builder... } diff --git a/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java b/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java index f111e577bf1..20c934f15c6 100644 --- a/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java +++ b/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java @@ -253,12 +253,12 @@ public class MBeanServerInvocationHandler implements InvocationHandler { boolean notificationBroadcaster) { final InvocationHandler handler = new MBeanServerInvocationHandler(connection, objectName); - final Class[] interfaces; + final Class[] interfaces; if (notificationBroadcaster) { interfaces = - new Class[] {interfaceClass, NotificationEmitter.class}; + new Class[] {interfaceClass, NotificationEmitter.class}; } else - interfaces = new Class[] {interfaceClass}; + interfaces = new Class[] {interfaceClass}; Object proxy = Proxy.newProxyInstance(interfaceClass.getClassLoader(), @@ -269,7 +269,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - final Class methodClass = method.getDeclaringClass(); + final Class methodClass = method.getDeclaringClass(); if (methodClass.equals(NotificationBroadcaster.class) || methodClass.equals(NotificationEmitter.class)) @@ -285,8 +285,8 @@ public class MBeanServerInvocationHandler implements InvocationHandler { return p.invoke(connection, objectName, method, args); } else { final String methodName = method.getName(); - final Class[] paramTypes = method.getParameterTypes(); - final Class returnType = method.getReturnType(); + final Class[] paramTypes = method.getParameterTypes(); + final Class returnType = method.getReturnType(); /* Inexplicably, InvocationHandler specifies that args is null when the method takes no arguments rather than a @@ -361,7 +361,13 @@ public class MBeanServerInvocationHandler implements InvocationHandler { if (p != null) return p; } - p = new MXBeanProxy(mxbeanInterface, mappingFactory); + try { + p = new MXBeanProxy(mxbeanInterface, mappingFactory); + } catch (IllegalArgumentException e) { + String msg = "Cannot make MXBean proxy for " + + mxbeanInterface.getName() + ": " + e.getMessage(); + throw new IllegalArgumentException(msg, e.getCause()); + } classToProxy.put(mxbeanInterface, new WeakReference(p)); return p; } @@ -452,7 +458,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler { return true; if (methodName.equals("equals") && Arrays.equals(method.getParameterTypes(), - new Class[] {Object.class}) + new Class[] {Object.class}) && isLocal(proxy, method)) return true; return false; diff --git a/jdk/src/share/classes/javax/management/NotificationListener.java b/jdk/src/share/classes/javax/management/NotificationListener.java index eb29f8bd072..1e7b26c10d8 100644 --- a/jdk/src/share/classes/javax/management/NotificationListener.java +++ b/jdk/src/share/classes/javax/management/NotificationListener.java @@ -39,11 +39,10 @@ public interface NotificationListener extends java.util.EventListener { * blocking its notification broadcaster. * * @param notification The notification. - * @param handback An opaque object which helps the listener to associate information - * regarding the MBean emitter. This object is passed to the MBean during the - * addListener call and resent, without modification, to the listener. The MBean object - * should not use or modify the object. - * + * @param handback An opaque object which helps the listener to associate + * information regarding the MBean emitter. This object is passed to the + * addNotificationListener call and resent, without modification, to the + * listener. */ - public void handleNotification(Notification notification, Object handback) ; + public void handleNotification(Notification notification, Object handback); } diff --git a/jdk/src/share/classes/javax/management/StandardMBean.java b/jdk/src/share/classes/javax/management/StandardMBean.java index a779e8282bb..492b259d189 100644 --- a/jdk/src/share/classes/javax/management/StandardMBean.java +++ b/jdk/src/share/classes/javax/management/StandardMBean.java @@ -689,7 +689,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { getImplementationClass().getName()); } - MBeanSupport msupport = mbean; + MBeanSupport msupport = mbean; final MBeanInfo bi = msupport.getMBeanInfo(); final Object impl = msupport.getWrappedObject(); @@ -1391,8 +1391,8 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * garbage collected just because we know whether its MBeanInfo * is immutable. */ - private static final Map mbeanInfoSafeMap = - new WeakHashMap(); + private static final Map, Boolean> mbeanInfoSafeMap = + new WeakHashMap, Boolean>(); /** * Return true if {@code subclass} is known to preserve the immutability @@ -1438,9 +1438,9 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { private static class MBeanInfoSafeAction implements PrivilegedAction { - private final Class subclass; + private final Class subclass; - MBeanInfoSafeAction(Class subclass) { + MBeanInfoSafeAction(Class subclass) { this.subclass = subclass; } @@ -1454,13 +1454,13 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { // Check for "MBeanInfo getCachedMBeanInfo()" method. // if (overrides(subclass, StandardMBean.class, - "getCachedMBeanInfo", (Class[]) null)) + "getCachedMBeanInfo", (Class[]) null)) return false; // Check for "MBeanInfo getMBeanInfo()" method. // if (overrides(subclass, StandardMBean.class, - "getMBeanInfo", (Class[]) null)) + "getMBeanInfo", (Class[]) null)) return false; // Check for "MBeanNotificationInfo[] getNotificationInfo()" @@ -1473,7 +1473,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { // if (StandardEmitterMBean.class.isAssignableFrom(subclass)) if (overrides(subclass, StandardEmitterMBean.class, - "getNotificationInfo", (Class[]) null)) + "getNotificationInfo", (Class[]) null)) return false; return true; } diff --git a/jdk/src/share/classes/javax/management/event/EventClient.java b/jdk/src/share/classes/javax/management/event/EventClient.java index cfce77b0879..96c4017e450 100644 --- a/jdk/src/share/classes/javax/management/event/EventClient.java +++ b/jdk/src/share/classes/javax/management/event/EventClient.java @@ -117,12 +117,12 @@ public class EventClient implements EventConsumer, NotificationManager { public static final String NONFATAL = "jmx.event.service.nonfatal"; /** - *

    A notification string type used by an {@code EventClient} object to - * inform a listener added by {@code #addEventClientListener} that it - * has detected that notifications have been lost. The {@link - * Notification#getUserData() userData} of the notification is a Long which - * is an upper bound on the number of lost notifications that have just - * been detected.

    + *

    A notification string type used by an {@code EventClient} object + * to inform a listener added by {@link #addEventClientListener + * addEventClientListener} that it has detected that notifications have + * been lost. The {@link Notification#getUserData() userData} of the + * notification is a Long which is an upper bound on the number of lost + * notifications that have just been detected.

    * * @see #addEventClientListener */ @@ -577,8 +577,13 @@ public class EventClient implements EventConsumer, NotificationManager { } /** - * Returns the set of listeners that have been added through - * this {@code EventClient} and not subsequently removed. + *

    Returns the collection of listeners that have been added through + * this {@code EventClient} and not subsequently removed. The returned + * collection contains one entry for every listener added with + * {@link #addNotificationListener addNotificationListener} or + * {@link #subscribe subscribe} and not subsequently removed with + * {@link #removeNotificationListener removeNotificationListener} or + * {@link #unsubscribe unsubscribe}, respectively.

    * * @return A collection of listener information. Empty if there are no * current listeners or if this {@code EventClient} has been {@linkplain @@ -927,8 +932,10 @@ public class EventClient implements EventConsumer, NotificationManager { private final static MBeanNotificationInfo[] myInfo = new MBeanNotificationInfo[] { new MBeanNotificationInfo( - new String[] {FAILED, NOTIFS_LOST}, - Notification.class.getName(), "")}; + new String[] {FAILED, NONFATAL, NOTIFS_LOST}, + Notification.class.getName(), + "Notifications that can be sent to a listener added with " + + "EventClient.addEventClientListener")}; private final NotificationBroadcasterSupport broadcaster = new NotificationBroadcasterSupport(); diff --git a/jdk/src/share/classes/javax/management/event/EventClientDelegate.java b/jdk/src/share/classes/javax/management/event/EventClientDelegate.java index 8d144123a87..13329ea9e6f 100644 --- a/jdk/src/share/classes/javax/management/event/EventClientDelegate.java +++ b/jdk/src/share/classes/javax/management/event/EventClientDelegate.java @@ -104,8 +104,8 @@ public class EventClientDelegate implements EventClientDelegateMBean { public static EventClientDelegate getEventClientDelegate(MBeanServer server) { EventClientDelegate delegate = null; synchronized(delegateMap) { - final WeakReference wrf = delegateMap.get(server); - delegate = (wrf == null) ? null : (EventClientDelegate)wrf.get(); + final WeakReference wrf = delegateMap.get(server); + delegate = (wrf == null) ? null : wrf.get(); if (delegate == null) { delegate = new EventClientDelegate(server); @@ -282,7 +282,7 @@ public class EventClientDelegate implements EventClientDelegateMBean { Constructor foundCons = null; if (sig == null) sig = new String[0]; - for (Constructor cons : c.getConstructors()) { + for (Constructor cons : c.getConstructors()) { Class[] types = cons.getParameterTypes(); String[] consSig = new String[types.length]; for (int i = 0; i < types.length; i++) diff --git a/jdk/src/share/classes/javax/management/event/EventSubscriber.java b/jdk/src/share/classes/javax/management/event/EventSubscriber.java index 9948810bfeb..5a472b5adb5 100644 --- a/jdk/src/share/classes/javax/management/event/EventSubscriber.java +++ b/jdk/src/share/classes/javax/management/event/EventSubscriber.java @@ -350,8 +350,7 @@ public class EventSubscriber implements EventConsumer { static { QueryExp broadcasterExp; try { - final Method m = Query.class.getMethod("isInstanceOf", - new Class[] {String.class}); + final Method m = Query.class.getMethod("isInstanceOf", String.class); broadcasterExp = (QueryExp)m.invoke(Query.class, new Object[] {NotificationBroadcaster.class.getName()}); } catch (Exception e) { diff --git a/jdk/src/share/classes/javax/management/loading/DefaultLoaderRepository.java b/jdk/src/share/classes/javax/management/loading/DefaultLoaderRepository.java index 0d514dd780a..5c2717c256d 100644 --- a/jdk/src/share/classes/javax/management/loading/DefaultLoaderRepository.java +++ b/jdk/src/share/classes/javax/management/loading/DefaultLoaderRepository.java @@ -69,7 +69,7 @@ public class DefaultLoaderRepository { * @exception ClassNotFoundException The specified class could not be * found. */ - public static Class loadClass(String className) + public static Class loadClass(String className) throws ClassNotFoundException { MBEANSERVER_LOGGER.logp(Level.FINEST, DefaultLoaderRepository.class.getName(), @@ -93,7 +93,7 @@ public class DefaultLoaderRepository { * @exception ClassNotFoundException The specified class could not be * found. */ - public static Class loadClassWithout(ClassLoader loader, + public static Class loadClassWithout(ClassLoader loader, String className) throws ClassNotFoundException { MBEANSERVER_LOGGER.logp(Level.FINEST, @@ -102,12 +102,11 @@ public class DefaultLoaderRepository { return load(loader, className); } - private static Class load(ClassLoader without, String className) + private static Class load(ClassLoader without, String className) throws ClassNotFoundException { - final List mbsList = MBeanServerFactory.findMBeanServer(null); + final List mbsList = MBeanServerFactory.findMBeanServer(null); - for (Iterator it = mbsList.iterator(); it.hasNext(); ) { - MBeanServer mbs = (MBeanServer) it.next(); + for (MBeanServer mbs : mbsList) { ClassLoaderRepository clr = mbs.getClassLoaderRepository(); try { return clr.loadClassWithout(without, className); diff --git a/jdk/src/share/classes/javax/management/loading/MLet.java b/jdk/src/share/classes/javax/management/loading/MLet.java index d6540591e98..c006dc09b11 100644 --- a/jdk/src/share/classes/javax/management/loading/MLet.java +++ b/jdk/src/share/classes/javax/management/loading/MLet.java @@ -1291,7 +1291,7 @@ public class MLet extends java.net.URLClassLoader if (c != null) { try { Constructor cons = - c.getConstructor(new Class[] {String.class}); + c.getConstructor(String.class); Object[] oo = new Object[1]; oo[0]=param; return(cons.newInstance(oo)); diff --git a/jdk/src/share/classes/javax/management/loading/MLetObjectInputStream.java b/jdk/src/share/classes/javax/management/loading/MLetObjectInputStream.java index 8f9ea4cc69a..06262dc5aed 100644 --- a/jdk/src/share/classes/javax/management/loading/MLetObjectInputStream.java +++ b/jdk/src/share/classes/javax/management/loading/MLetObjectInputStream.java @@ -55,30 +55,30 @@ class MLetObjectInputStream extends ObjectInputStream { this.loader = loader; } - private Class primitiveType(char c) { + private Class primitiveType(char c) { switch(c) { - case 66: /* 'B' */ + case 'B': return Byte.TYPE; - case 67: /* 'C' */ + case 'C': return Character.TYPE; - case 68: /* 'D' */ + case 'D': return Double.TYPE; - case 70: /* 'F' */ + case 'F': return Float.TYPE; - case 73: /* 'I' */ + case 'I': return Integer.TYPE; - case 74: /* 'J' */ + case 'J': return Long.TYPE; - case 83: /* 'S' */ + case 'S': return Short.TYPE; - case 90: /* 'Z' */ + case 'Z': return Boolean.TYPE; } return null; @@ -87,14 +87,15 @@ class MLetObjectInputStream extends ObjectInputStream { /** * Use the given ClassLoader rather than using the system class */ - protected Class resolveClass(ObjectStreamClass objectstreamclass) + @Override + protected Class resolveClass(ObjectStreamClass objectstreamclass) throws IOException, ClassNotFoundException { String s = objectstreamclass.getName(); if (s.startsWith("[")) { int i; for (i = 1; s.charAt(i) == '['; i++); - Class class1; + Class class1; if (s.charAt(i) == 'L') { class1 = loader.loadClass(s.substring(i + 1, s.length() - 1)); } else { diff --git a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java index 66b8fec8b9a..ee8e3030e54 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -589,7 +589,7 @@ public class DescriptorSupport int numberOfEntries = descriptorMap.size(); String[] responseFields = new String[numberOfEntries]; - Set returnedSet = descriptorMap.entrySet(); + Set> returnedSet = descriptorMap.entrySet(); int i = 0; @@ -598,8 +598,9 @@ public class DescriptorSupport DescriptorSupport.class.getName(), "getFields()", "Returning " + numberOfEntries + " fields"); } - for (Iterator iter = returnedSet.iterator(); iter.hasNext(); i++) { - Map.Entry currElement = (Map.Entry) iter.next(); + for (Iterator> iter = returnedSet.iterator(); + iter.hasNext(); i++) { + Map.Entry currElement = iter.next(); if (currElement == null) { if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { @@ -642,7 +643,7 @@ public class DescriptorSupport int numberOfEntries = descriptorMap.size(); String[] responseFields = new String[numberOfEntries]; - Set returnedSet = descriptorMap.entrySet(); + Set> returnedSet = descriptorMap.entrySet(); int i = 0; @@ -653,8 +654,9 @@ public class DescriptorSupport "Returning " + numberOfEntries + " fields"); } - for (Iterator iter = returnedSet.iterator(); iter.hasNext(); i++) { - Map.Entry currElement = (Map.Entry) iter.next(); + for (Iterator> iter = returnedSet.iterator(); + iter.hasNext(); i++) { + Map.Entry currElement = iter.next(); if (( currElement == null ) || (currElement.getKey() == null)) { if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { @@ -700,9 +702,8 @@ public class DescriptorSupport } if (fieldNames == null) { - for (Iterator iter = descriptorMap.values().iterator(); - iter.hasNext(); i++) - responseFields[i] = iter.next(); + for (Object value : descriptorMap.values()) + responseFields[i++] = value; } else { for (i=0; i < fieldNames.length; i++) { if ((fieldNames[i] == null) || (fieldNames[i].equals(""))) { @@ -883,9 +884,9 @@ public class DescriptorSupport * not a String with value "t", "f", "true", "false". These String * values must not be case sensitive. *
  • visibility fieldName, if defined, is null, or not a - * Numeric String or a not Numeric Value >= 1 and <= 4 + * Numeric String or a not Numeric Value >= 1 and <= 4 *
  • severity fieldName, if defined, is null, or not a Numeric - * String or not a Numeric Value >= 0 and <= 6
    + * String or not a Numeric Value >= 0 and <= 6
    *
  • persistPolicy fieldName, if defined, is null, or not one of * the following strings:
    * "OnUpdate", "OnTimer", "NoMoreOftenThan", "OnUnregister", "Always", @@ -904,7 +905,7 @@ public class DescriptorSupport } // verify that the descriptor is valid, by iterating over each field... - Set returnedSet = descriptorMap.entrySet(); + Set> returnedSet = descriptorMap.entrySet(); if (returnedSet == null) { // null descriptor, not valid if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { @@ -925,9 +926,7 @@ public class DescriptorSupport // According to the descriptor type we validate the fields contained - for (Iterator iter = returnedSet.iterator(); iter.hasNext();) { - Map.Entry currElement = (Map.Entry) iter.next(); - + for (Map.Entry currElement : returnedSet) { if (currElement != null) { if (currElement.getValue() != null) { // validate the field valued... @@ -1083,10 +1082,9 @@ public class DescriptorSupport */ public synchronized String toXMLString() { final StringBuilder buf = new StringBuilder(""); - Set returnedSet = descriptorMap.entrySet(); - for (Iterator iter = returnedSet.iterator(); iter.hasNext(); ) { - final Map.Entry currElement = (Map.Entry) iter.next(); - final String name = currElement.getKey().toString(); + Set> returnedSet = descriptorMap.entrySet(); + for (Map.Entry currElement : returnedSet) { + final String name = currElement.getKey(); Object value = currElement.getValue(); String valueString = null; /* Set valueString to non-null if and only if this is a string that @@ -1256,7 +1254,7 @@ public class DescriptorSupport } final Class c = Class.forName(className, false, contextClassLoader); - constr = c.getConstructor(new Class[] {String.class}); + constr = c.getConstructor(new Class[] {String.class}); } catch (Exception e) { throw new XMLParseException(e, "Cannot parse value: <" + s + ">"); diff --git a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java index cc2ec0b7a41..9ee9a6b4635 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java @@ -39,7 +39,6 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.lang.reflect.Method; import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.logging.Level; import javax.management.Descriptor; @@ -49,32 +48,56 @@ import javax.management.MBeanAttributeInfo; import javax.management.RuntimeOperationsException; /** - * The ModelMBeanAttributeInfo object describes an attribute of the ModelMBean. + *

    The ModelMBeanAttributeInfo object describes an attribute of the ModelMBean. * It is a subclass of MBeanAttributeInfo with the addition of an associated Descriptor - * and an implementation of the DescriptorAccess interface. - *

    - * The fields in the descriptor are defined, but not limited to, the following:

    - *

    - * name           : attribute name
    - * descriptorType : must be "attribute"
    - * value          : current value for attribute
    - * default        : default value for attribute
    - * displayName    : name of attribute to be used in displays
    - * getMethod      : name of operation descriptor for get method
    - * setMethod      : name of operation descriptor for set method
    - * protocolMap    : object which implements the Descriptor interface: mappings
    - *                  must be appropriate for the attribute
    - *                  and entries can be updated or augmented at runtime.
    - * persistPolicy  : OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never
    - * persistPeriod  : seconds - frequency of persist cycle. Used when persistPolicy
    - *                  is "OnTimer" or "NoMoreOftenThan".
    - * currencyTimeLimit : how long value is valid, <0 never, =0 always, >0 seconds
    - * lastUpdatedTimeStamp : when value was set
    - * visibility     : 1-4 where 1: always visible, 4: rarely visible
    - * presentationString : xml formatted string to allow presentation of data
    - * 
    - * The default descriptor contains the name, descriptorType and displayName fields. - * The default value of the name and displayName fields is the name of the attribute. + * and an implementation of the DescriptorAccess interface.

    + * + *

    + * The fields in the descriptor are defined, but not limited to, the following. + * Note that when the Type in this table is Number, a String that is the decimal + * representation of a Long can also be used.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeMeaning
    nameStringAttribute name.
    descriptorTypeStringMust be "attribute".
    valueObjectCurrent (cached) value for attribute.
    defaultObjectDefault value for attribute.
    displayNameStringName of attribute to be used in displays.
    getMethodStringName of operation descriptor for get method.
    setMethodStringName of operation descriptor for set method.
    protocolMapDescriptorSee the section "Protocol Map Support" in the JMX specification + * document. Mappings must be appropriate for the attribute and entries + * can be updated or augmented at runtime.
    persistPolicyStringOne of: OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never. + * See the section "MBean Descriptor Fields" in the JMX specification + * document.
    persistPeriodNumberFrequency of persist cycle in seconds. Used when persistPolicy is + * "OnTimer" or "NoMoreOftenThan".
    currencyTimeLimitNumberHow long value is valid: <0 never, + * =0 always, >0 seconds.
    lastUpdatedTimeStampNumberWhen value was set.
    visibilityNumber1-4 where 1: always visible, 4: rarely visible.
    presentationStringStringXML formatted string to allow presentation of data.
    + * + *

    The default descriptor contains the name, descriptorType and displayName + * fields. The default value of the name and displayName fields is the name of + * the attribute.

    * *

    Note: because of inconsistencies in previous versions of * this specification, it is recommended not to use negative or zero diff --git a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java index a6e7ceab737..ecf8ecf002b 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java @@ -49,22 +49,33 @@ import javax.management.MBeanParameterInfo; import javax.management.RuntimeOperationsException; /** - * The ModelMBeanConstructorInfo object describes a constructor of the ModelMBean. + *

    The ModelMBeanConstructorInfo object describes a constructor of the ModelMBean. * It is a subclass of MBeanConstructorInfo with the addition of an associated Descriptor - * and an implementation of the DescriptorAccess interface. - *

    - *

    - * The fields in the descriptor are defined, but not limited to, the following: 

    - * name : constructor name - * descriptorType : must be "operation" - * role : must be "constructor" - * displayName : human readable name of constructor - * visibility : 1-4 where 1: always visible 4: rarely visible - * presentationString : xml formatted string to describe how to present operation - *

    + * and an implementation of the DescriptorAccess interface.

    + * + *

    + * The fields in the descriptor are defined, but not limited to, the following. + * Note that when the Type in this table is Number, a String that is the decimal + * representation of a Long can also be used.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeMeaning
    nameStringConstructor name.
    descriptorTypeStringMust be "operation".
    roleStringMust be "constructor".
    displayNameStringHuman readable name of constructor.
    visibilityNumber1-4 where 1: always visible 4: rarely visible.
    presentationStringStringXML formatted string to describe how to present operation
    * *

    The {@code persistPolicy} and {@code currencyTimeLimit} fields - * are meaningless for constructors, but are not considered invalid. + * are meaningless for constructors, but are not considered invalid.

    * *

    The default descriptor will have the {@code name}, {@code * descriptorType}, {@code displayName} and {@code role} fields. The @@ -152,7 +163,7 @@ public class ModelMBeanConstructorInfo * describing the MBean constructor. */ public ModelMBeanConstructorInfo(String description, - Constructor constructorMethod) + Constructor constructorMethod) { super(description, constructorMethod); if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { @@ -194,7 +205,7 @@ public class ModelMBeanConstructorInfo */ public ModelMBeanConstructorInfo(String description, - Constructor constructorMethod, + Constructor constructorMethod, Descriptor descriptor) { diff --git a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java index 367e616eb09..70c0e74f9f2 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java @@ -156,29 +156,55 @@ public interface ModelMBeanInfo /** - * Returns the ModelMBean's descriptor which contains MBean wide policies. This descriptor contains - * metadata about the MBean and default policies for persistence and caching. - *

    - * The fields in the descriptor are defined, but not limited to, the following: - *

    -     * name           : MBean name
    -     * descriptorType : must be "mbean"
    -     * displayName    : name of attribute to be used in displays
    -     * persistPolicy  : OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never
    -     * persistLocation : The fully qualified directory name where the MBean should be persisted (if appropriate)
    -     * persistFile    : File name into which the MBean should be persisted
    -     * persistPeriod  : seconds - frequency of persist cycle for OnTime and NoMoreOftenThan PersistPolicy
    -     * currencyTimeLimit : how long value is valid, <0 never, =0 always, >0 seconds
    -     * log            : where t: log all notifications f: log no notifications
    -     * logfile        : fully qualified filename to log events to
    -     * visibility     : 1-4 where 1: always visible 4: rarely visible
    -     * export         : name to be used to export/expose this MBean so that it is findable by
    -     *                  other JMX Agents.
    -     * presentationString : xml formatted string to allow presentation of data to be associated with the MBean.
    -     * 
    + *

    Returns the ModelMBean's descriptor which contains MBean wide + * policies. This descriptor contains metadata about the MBean and default + * policies for persistence and caching.

    + * + *

    + * The fields in the descriptor are defined, but not limited to, the + * following. Note that when the Type in this table is Number, a String + * that is the decimal representation of a Long can also be used.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeMeaning
    nameStringMBean name.
    descriptorTypeStringMust be "mbean".
    displayNameStringName of MBean to be used in displays.
    persistPolicyStringOne of: OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never. + * See the section "MBean Descriptor Fields" in the JMX specification + * document.
    persistLocationStringThe fully qualified directory name where the MBean should be + * persisted (if appropriate).
    persistFileStringFile name into which the MBean should be persisted.
    persistPeriodNumberFrequency of persist cycle in seconds, for OnTime and + * NoMoreOftenThan PersistPolicy
    currencyTimeLimitNumberHow long cached value is valid: <0 never, =0 always, + * >0 seconds.
    logStringt: log all notifications, f: log no notifications.
    logfileStringFully qualified filename to log events to.
    visibilityNumber1-4 where 1: always visible 4: rarely visible.
    exportStringName to be used to export/expose this MBean so that it is + * findable by other JMX Agents.
    presentationStringStringXML formatted string to allow presentation of data to be + * associated with the MBean.
    + * *

    * The default descriptor is: name=className,descriptorType="mbean", displayName=className, - * persistPolicy="never",log="F",export="F",visibility="1" + * persistPolicy="never",log="F",visibility="1" * If the descriptor does not contain all these fields, they will be added with these default values. * *

    Note: because of inconsistencies in previous versions of @@ -207,7 +233,7 @@ public interface ModelMBeanInfo * does a complete replacement of the descriptor, no merging is done. If the descriptor to * set to is null then the default descriptor will be created. * The default descriptor is: name=className,descriptorType="mbean", displayName=className, - * persistPolicy="never",log="F",export="F",visibility="1" + * persistPolicy="never",log="F",visibility="1" * If the descriptor does not contain all these fields, they will be added with these default values. * * See {@link #getMBeanDescriptor getMBeanDescriptor} method javadoc for description of valid field names. diff --git a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java index 52f1317db81..4b637ee08f8 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java @@ -46,34 +46,46 @@ import javax.management.MBeanNotificationInfo; import javax.management.RuntimeOperationsException; /** - * The ModelMBeanNotificationInfo object describes a notification emitted + *

    The ModelMBeanNotificationInfo object describes a notification emitted * by a ModelMBean. * It is a subclass of MBeanNotificationInfo with the addition of an - * associated Descriptor and an implementation of the Descriptor interface. - *

    - * The fields in the descriptor are defined, but not limited to, - * the following: - *

    - * name           : notification name
    - * descriptorType : must be "notification"
    - * severity       : 0-6 where 0: unknown; 1: non-recoverable;
    - *                  2: critical, failure; 3: major, severe;
    - *                  4: minor, marginal, error; 5: warning;
    - *                  6: normal, cleared, informative
    - * messageID      : unique key for message text (to allow translation,
    - *                  analysis)
    - * messageText    : text of notification
    - * log            : T - log message F - do not log message
    - * logfile        : string fully qualified file name appropriate for
    - *                  operating system
    - * visibility     : 1-4 where 1: always visible 4: rarely visible
    - * presentationString : xml formatted string to allow presentation of data
    - * 
    - * The default descriptor contains the name, descriptorType, + * associated Descriptor and an implementation of the Descriptor interface.

    + * + *

    + * The fields in the descriptor are defined, but not limited to, the following. + * Note that when the Type in this table is Number, a String that is the decimal + * representation of a Long can also be used.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeMeaning
    nameStringNotification name.
    descriptorTypeStringMust be "notification".
    severityNumber0-6 where 0: unknown; 1: non-recoverable; + * 2: critical, failure; 3: major, severe; + * 4: minor, marginal, error; 5: warning; + * 6: normal, cleared, informative
    messageIDStringUnique key for message text (to allow translation, analysis).
    messageTextStringText of notification.
    logStringT - log message, F - do not log message.
    logfileStringfully qualified file name appropriate for operating system.
    visibilityNumber1-4 where 1: always visible 4: rarely visible.
    presentationStringStringXML formatted string to allow presentation of data.
    + * + *

    The default descriptor contains the name, descriptorType, * displayName and severity(=6) fields. The default value of the name * and displayName fields is the name of the Notification class (as * specified by the name parameter of the - * ModelMBeanNotificationInfo constructor). + * ModelMBeanNotificationInfo constructor).

    * *

    The serialVersionUID of this class is -7445681389570207141L. * diff --git a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java index 2ed99224067..6ebea49954d 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java @@ -49,27 +49,48 @@ import javax.management.MBeanParameterInfo; import javax.management.RuntimeOperationsException; /** - * The ModelMBeanOperationInfo object describes a management operation of the ModelMBean. - * It is a subclass of MBeanOperationInfo with the addition of an associated Descriptor - * and an implementation of the DescriptorAccess interface. - *

    - *

    - * The fields in the descriptor are defined, but not limited to, the following:
    - * name           : operation name
    - * descriptorType : must be "operation"
    - * class          : class where method is defined (fully qualified)
    - * role           : must be "operation", "getter", or "setter
    - * targetObject   : object on which to execute this method
    - * targetType     : type of object reference for targetObject. Can be:
    - *                  ObjectReference | Handle | EJBHandle | IOR | RMIReference.
    - * value          : cached value for operation
    - * currencyTimeLimit : how long cached value is valid
    - * lastUpdatedTimeStamp : when cached value was set
    - * visibility            : 1-4 where 1: always visible 4: rarely visible
    - * presentationString :  xml formatted string to describe how to present operation
    - * 
    - * The default descriptor will have name, descriptorType, displayName and role fields set. - * The default value of the name and displayName fields is the operation name. + *

    The ModelMBeanOperationInfo object describes a management operation of + * the ModelMBean. It is a subclass of MBeanOperationInfo with the addition + * of an associated Descriptor and an implementation of the DescriptorAccess + * interface.

    + * + *

    + * The fields in the descriptor are defined, but not limited to, the following. + * Note that when the Type in this table is Number, a String that is the decimal + * representation of a Long can also be used.

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeMeaning
    nameStringOperation name.
    descriptorTypeStringMust be "operation".
    classStringClass where method is defined (fully qualified).
    roleStringMust be "operation", "getter", or "setter".
    targetObjectObjectObject on which to execute this method.
    targetTypeStringtype of object reference for targetObject. Can be: + * ObjectReference | Handle | EJBHandle | IOR | RMIReference.
    valueObjectCached value for operation.
    displayNameStringHuman readable display name of the operation.
    currencyTimeLimitNumberHow long cached value is valid.
    lastUpdatedTimeStampNumberWhen cached value was set.
    visibilityNumber1-4 where 1: always visible 4: rarely visible.
    presentationStringStringXML formatted string to describe how to present operation
    + * + *

    The default descriptor will have name, descriptorType, displayName and + * role fields set. The default value of the name and displayName fields is + * the operation name.

    * *

    Note: because of inconsistencies in previous versions of * this specification, it is recommended not to use negative or zero diff --git a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java index 7d99fba0021..b9bec5ecc86 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -1074,7 +1074,7 @@ public class RequiredModelMBean } } - final Class targetClass; + final Class targetClass; if (opClassName != null) { try { @@ -1126,20 +1126,20 @@ public class RequiredModelMBean "resolving " + targetClass.getName() + "." + opMethodName); } - final Class[] argClasses; + final Class[] argClasses; if (sig == null) argClasses = null; else { final ClassLoader targetClassLoader = targetClass.getClassLoader(); - argClasses = new Class[sig.length]; + argClasses = new Class[sig.length]; for (int i = 0; i < sig.length; i++) { if (tracing) { MODELMBEAN_LOGGER.logp(Level.FINER, RequiredModelMBean.class.getName(),"resolveMethod", "resolve type " + sig[i]); } - argClasses[i] = (Class) primitiveClassMap.get(sig[i]); + argClasses[i] = (Class) primitiveClassMap.get(sig[i]); if (argClasses[i] == null) { try { argClasses[i] = @@ -1170,7 +1170,7 @@ public class RequiredModelMBean /* Map e.g. "int" to int.class. Goodness knows how many time this particular wheel has been reinvented. */ - private static final Class[] primitiveClasses = { + private static final Class[] primitiveClasses = { int.class, long.class, boolean.class, double.class, float.class, short.class, byte.class, char.class, }; @@ -1178,7 +1178,7 @@ public class RequiredModelMBean new HashMap>(); static { for (int i = 0; i < primitiveClasses.length; i++) { - final Class c = primitiveClasses[i]; + final Class c = primitiveClasses[i]; primitiveClassMap.put(c.getName(), c); } } @@ -1645,7 +1645,7 @@ public class RequiredModelMBean try { ClassLoader cl = response.getClass().getClassLoader(); - Class c = Class.forName(respType, true, cl); + Class c = Class.forName(respType, true, cl); subtype = c.isInstance(response); } catch (Exception e) { subtype = false; @@ -1904,7 +1904,7 @@ public class RequiredModelMBean if (attrSetMethod == null) { if (attrValue != null) { try { - final Class clazz = loadClass(attrType); + final Class clazz = loadClass(attrType); if (! clazz.isInstance(attrValue)) throw new InvalidAttributeValueException(clazz.getName() + " expected, " + @@ -2044,8 +2044,7 @@ public class RequiredModelMBean final AttributeList responseList = new AttributeList(); // Go through the list of attributes - for (Iterator i = attributes.iterator(); i.hasNext();) { - final Attribute attr = (Attribute) i.next(); + for (Attribute attr : attributes.asList()) { try { setAttribute(attr); responseList.add(attr); @@ -2799,7 +2798,7 @@ public class RequiredModelMBean return MBeanServerFactory.getClassLoaderRepository(server); } - private Class loadClass(String className) + private Class loadClass(String className) throws ClassNotFoundException { try { return Class.forName(className); diff --git a/jdk/src/share/classes/javax/management/namespace/MBeanServerSupport.java b/jdk/src/share/classes/javax/management/namespace/MBeanServerSupport.java index 903be3c308f..ea070ae262e 100644 --- a/jdk/src/share/classes/javax/management/namespace/MBeanServerSupport.java +++ b/jdk/src/share/classes/javax/management/namespace/MBeanServerSupport.java @@ -457,7 +457,11 @@ public abstract class MBeanServerSupport implements MBeanServer { * All the various flavors of {@code MBeanServer.createMBean} methods * will eventually call this method. A subclass that wishes to * support MBean creation through {@code createMBean} thus only - * needs to provide an implementation for this one method. + * needs to provide an implementation for this one method.

    + * + *

    A subclass implementation of this method should respect the contract + * of the various {@code createMBean} methods in the {@link MBeanServer} + * interface, in particular as regards exception wrapping.

    * * @param className The class name of the MBean to be instantiated. * @param name The object name of the MBean. May be null. @@ -488,6 +492,17 @@ public abstract class MBeanServerSupport implements MBeanServer { * preRegister (MBeanRegistration * interface) method of the MBean has thrown an exception. The * MBean will not be registered. + * @exception RuntimeMBeanException If the MBean's constructor or its + * {@code preRegister} or {@code postRegister} method threw + * a {@code RuntimeException}. If the postRegister + * (MBeanRegistration interface) method of the MBean throws a + * RuntimeException, the createMBean method will + * throw a RuntimeMBeanException, although the MBean creation + * and registration succeeded. In such a case, the MBean will be actually + * registered even though the createMBean method + * threw an exception. Note that RuntimeMBeanException can + * also be thrown by preRegister, in which case the MBean + * will not be registered. * @exception MBeanException The constructor of the MBean has * thrown an exception * @exception NotCompliantMBeanException This class is not a JMX @@ -1096,7 +1111,7 @@ public abstract class MBeanServerSupport implements MBeanServer { MBeanRegistrationException, MBeanException, NotCompliantMBeanException { try { - return safeCreateMBean(className, name, null, params, signature, true); + return createMBean(className, name, null, params, signature, true); } catch (InstanceNotFoundException ex) { // should not happen! throw new MBeanException(ex, "Unexpected exception: " + ex); @@ -1113,7 +1128,7 @@ public abstract class MBeanServerSupport implements MBeanServer { throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException { - return safeCreateMBean(className, name, loaderName, params, signature, false); + return createMBean(className, name, loaderName, params, signature, false); } /** @@ -1126,7 +1141,7 @@ public abstract class MBeanServerSupport implements MBeanServer { MBeanRegistrationException, MBeanException, NotCompliantMBeanException { try { - return safeCreateMBean(className, name, null, null, null, true); + return createMBean(className, name, null, null, null, true); } catch (InstanceNotFoundException ex) { // should not happen! throw new MBeanException(ex, "Unexpected exception: " + ex); @@ -1143,32 +1158,7 @@ public abstract class MBeanServerSupport implements MBeanServer { throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException { - return safeCreateMBean(className, name, loaderName, null, null, false); - } - - // make sure all exceptions are correctly wrapped in a JMXException - private ObjectInstance safeCreateMBean(String className, - ObjectName name, ObjectName loaderName, Object[] params, - String[] signature, boolean useRepository) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - try { - return createMBean(className, name, loaderName, params, - signature, useRepository); - } catch (ReflectionException x) { throw x; - } catch (InstanceAlreadyExistsException x) { throw x; - } catch (MBeanRegistrationException x) { throw x; - } catch (MBeanException x) { throw x; - } catch (NotCompliantMBeanException x) { throw x; - } catch (InstanceNotFoundException x) { throw x; - } catch (SecurityException x) { throw x; - } catch (JMRuntimeException x) { throw x; - } catch (RuntimeException x) { - throw new RuntimeOperationsException(x, x.toString()); - } catch (Exception x) { - throw new MBeanException(x, x.toString()); - } + return createMBean(className, name, loaderName, null, null, false); } diff --git a/jdk/src/share/classes/javax/management/openmbean/ArrayType.java b/jdk/src/share/classes/javax/management/openmbean/ArrayType.java index 49c8bbf1f63..0cbb677cf88 100644 --- a/jdk/src/share/classes/javax/management/openmbean/ArrayType.java +++ b/jdk/src/share/classes/javax/management/openmbean/ArrayType.java @@ -296,7 +296,7 @@ public class ArrayType extends OpenType { // Check and construct state specific to ArrayType // if (elementType.isArray()) { - ArrayType at = (ArrayType) elementType; + ArrayType at = (ArrayType) elementType; this.dimension = at.getDimension() + dimension; this.elementType = at.getElementOpenType(); this.primitiveArray = at.isPrimitiveArray(); @@ -384,7 +384,7 @@ public class ArrayType extends OpenType { /* Package-private constructor for callers we trust to get it right. */ ArrayType(String className, String typeName, String description, - int dimension, OpenType elementType, + int dimension, OpenType elementType, boolean primitiveArray) { super(className, typeName, description, true); this.dimension = dimension; @@ -397,7 +397,7 @@ public class ArrayType extends OpenType { throws OpenDataException { boolean isPrimitiveArray = false; if (elementType.isArray()) { - isPrimitiveArray = ((ArrayType) elementType).isPrimitiveArray(); + isPrimitiveArray = ((ArrayType) elementType).isPrimitiveArray(); } return buildArrayClassName(dimension, elementType, isPrimitiveArray); } @@ -443,7 +443,7 @@ public class ArrayType extends OpenType { throws OpenDataException { boolean isPrimitiveArray = false; if (elementType.isArray()) { - isPrimitiveArray = ((ArrayType) elementType).isPrimitiveArray(); + isPrimitiveArray = ((ArrayType) elementType).isPrimitiveArray(); } return buildArrayDescription(dimension, elementType, isPrimitiveArray); } @@ -453,7 +453,7 @@ public class ArrayType extends OpenType { boolean isPrimitiveArray) throws OpenDataException { if (elementType.isArray()) { - ArrayType at = (ArrayType) elementType; + ArrayType at = (ArrayType) elementType; dimension += at.getDimension(); elementType = at.getElementOpenType(); isPrimitiveArray = at.isPrimitiveArray(); @@ -551,7 +551,7 @@ public class ArrayType extends OpenType { return false; } - Class objClass = obj.getClass(); + Class objClass = obj.getClass(); String objClassName = objClass.getName(); // if obj is not an array, return false @@ -636,8 +636,8 @@ public class ArrayType extends OpenType { } @Override - boolean isAssignableFrom(OpenType ot) { - if (!(ot instanceof ArrayType)) + boolean isAssignableFrom(OpenType ot) { + if (!(ot instanceof ArrayType)) return false; ArrayType at = (ArrayType) ot; return (at.getDimension() == getDimension() && @@ -675,9 +675,9 @@ public class ArrayType extends OpenType { // if obj is not an ArrayType, return false // - if (!(obj instanceof ArrayType)) + if (!(obj instanceof ArrayType)) return false; - ArrayType other = (ArrayType) obj; + ArrayType other = (ArrayType) obj; // if other's dimension is different than this instance's, return false // @@ -879,6 +879,7 @@ public class ArrayType extends OpenType { // Build primitive array // try { + @SuppressWarnings("rawtypes") ArrayType at = new ArrayType(simpleType, true); if (n > 1) at = new ArrayType(n - 1, at); @@ -934,7 +935,7 @@ public class ArrayType extends OpenType { } } - private ArrayType convertFromWrapperToPrimitiveTypes() { + private ArrayType convertFromWrapperToPrimitiveTypes() { String cn = getClassName(); String tn = getTypeName(); String d = getDescription(); @@ -952,8 +953,8 @@ public class ArrayType extends OpenType { break; } } - return new ArrayType(cn, tn, d, - dimension, elementType, primitiveArray); + return new ArrayType(cn, tn, d, + dimension, elementType, primitiveArray); } /** @@ -1002,7 +1003,7 @@ public class ArrayType extends OpenType { } } - private ArrayType convertFromPrimitiveToWrapperTypes() { + private ArrayType convertFromPrimitiveToWrapperTypes() { String cn = getClassName(); String tn = getTypeName(); String d = getDescription(); @@ -1020,7 +1021,7 @@ public class ArrayType extends OpenType { break; } } - return new ArrayType(cn, tn, d, - dimension, elementType, primitiveArray); + return new ArrayType(cn, tn, d, + dimension, elementType, primitiveArray); } } diff --git a/jdk/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java b/jdk/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java index e0414e9d031..2262c2a5ef7 100644 --- a/jdk/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java +++ b/jdk/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java @@ -236,8 +236,8 @@ public class CompositeDataInvocationHandler implements InvocationHandler { if (other == null) return false; - final Class proxyClass = proxy.getClass(); - final Class otherClass = other.getClass(); + final Class proxyClass = proxy.getClass(); + final Class otherClass = other.getClass(); if (proxyClass != otherClass) return false; InvocationHandler otherih = Proxy.getInvocationHandler(other); diff --git a/jdk/src/share/classes/javax/management/openmbean/CompositeType.java b/jdk/src/share/classes/javax/management/openmbean/CompositeType.java index b4c662ec9bc..28c3fd72b7f 100644 --- a/jdk/src/share/classes/javax/management/openmbean/CompositeType.java +++ b/jdk/src/share/classes/javax/management/openmbean/CompositeType.java @@ -329,7 +329,7 @@ public class CompositeType extends OpenType { * @return true if {@code ot} is assignable to this open type. */ @Override - boolean isAssignableFrom(OpenType ot) { + boolean isAssignableFrom(OpenType ot) { if (!(ot instanceof CompositeType)) return false; CompositeType ct = (CompositeType) ot; @@ -420,9 +420,7 @@ public class CompositeType extends OpenType { if (myHashCode == null) { int value = 0; value += this.getTypeName().hashCode(); - String key; - for (Iterator k = nameToDescription.keySet().iterator(); k.hasNext(); ) { - key = (String) k.next(); + for (String key : nameToDescription.keySet()) { value += key.hashCode(); value += this.nameToType.get(key).hashCode(); } @@ -457,10 +455,10 @@ public class CompositeType extends OpenType { result.append(getTypeName()); result.append(",items=("); int i=0; - Iterator k=nameToType.keySet().iterator(); + Iterator k=nameToType.keySet().iterator(); String key; while (k.hasNext()) { - key = (String) k.next(); + key = k.next(); if (i > 0) result.append(","); result.append("(itemName="); result.append(key); diff --git a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java index bcfa4c157ad..3ad03ef58ae 100644 --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java @@ -78,12 +78,12 @@ public class OpenMBeanAttributeInfoSupport /** * @serial The open mbean attribute's min value */ - private final Comparable minValue; + private final Comparable minValue; /** * @serial The open mbean attribute's max value */ - private final Comparable maxValue; + private final Comparable maxValue; // As this instance is immutable, these two values need only @@ -450,7 +450,7 @@ public class OpenMBeanAttributeInfoSupport } static void check(OpenMBeanParameterInfo info) throws OpenDataException { - OpenType openType = info.getOpenType(); + OpenType openType = info.getOpenType(); if (openType == null) throw new IllegalArgumentException("OpenType cannot be null"); @@ -562,7 +562,7 @@ public class OpenMBeanAttributeInfoSupport } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) static int compare(Object x, Object y) { return ((Comparable) x).compareTo(y); } @@ -657,11 +657,11 @@ public class OpenMBeanAttributeInfoSupport return result; } - static Comparable comparableValueFrom(Descriptor d, String name, - OpenType openType) { + static Comparable comparableValueFrom(Descriptor d, String name, + OpenType openType) { T t = valueFrom(d, name, openType); if (t == null || t instanceof Comparable) - return (Comparable) t; + return (Comparable) t; final String msg = "Descriptor field " + name + " with value " + t + " is not Comparable"; @@ -925,7 +925,7 @@ public class OpenMBeanAttributeInfoSupport return isValue(this, obj); } - @SuppressWarnings("unchecked") // cast to Comparable + @SuppressWarnings({"unchecked", "rawtypes"}) // cast to Comparable static boolean isValue(OpenMBeanParameterInfo info, Object obj) { if (info.hasDefaultValue() && obj == null) return true; diff --git a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanParameterInfoSupport.java b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanParameterInfoSupport.java index b67ac60d77c..fc50a3b7621 100644 --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanParameterInfoSupport.java +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanParameterInfoSupport.java @@ -74,12 +74,12 @@ public class OpenMBeanParameterInfoSupport /** * @serial The open mbean parameter's min value */ - private Comparable minValue = null; + private Comparable minValue = null; /** * @serial The open mbean parameter's max value */ - private Comparable maxValue = null; + private Comparable maxValue = null; // As this instance is immutable, these two values need only diff --git a/jdk/src/share/classes/javax/management/openmbean/OpenType.java b/jdk/src/share/classes/javax/management/openmbean/OpenType.java index 7aac2c0fd8f..3f74c3cda60 100644 --- a/jdk/src/share/classes/javax/management/openmbean/OpenType.java +++ b/jdk/src/share/classes/javax/management/openmbean/OpenType.java @@ -206,7 +206,7 @@ public abstract class OpenType implements Serializable { } } - private static boolean overridesGetClassName(final Class c) { + private static boolean overridesGetClassName(final Class c) { return AccessController.doPrivileged(new PrivilegedAction() { public Boolean run() { try { diff --git a/jdk/src/share/classes/javax/management/openmbean/SimpleType.java b/jdk/src/share/classes/javax/management/openmbean/SimpleType.java index 7837819c4c2..1d4f90e6a9b 100644 --- a/jdk/src/share/classes/javax/management/openmbean/SimpleType.java +++ b/jdk/src/share/classes/javax/management/openmbean/SimpleType.java @@ -163,7 +163,7 @@ public final class SimpleType extends OpenType { public static final SimpleType OBJECTNAME = new SimpleType(ObjectName.class); - private static final SimpleType[] typeArray = { + private static final SimpleType[] typeArray = { VOID, BOOLEAN, CHARACTER, BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, STRING, BIGDECIMAL, BIGINTEGER, DATE, OBJECTNAME, }; @@ -232,10 +232,10 @@ public final class SimpleType extends OpenType { return (this == obj); */ - if (!(obj instanceof SimpleType)) + if (!(obj instanceof SimpleType)) return false; - SimpleType other = (SimpleType) obj; + SimpleType other = (SimpleType) obj; // Test if other's className field is the same as for this instance // @@ -290,11 +290,11 @@ public final class SimpleType extends OpenType { return myToString; } - private static final Map canonicalTypes = - new HashMap(); + private static final Map,SimpleType> canonicalTypes = + new HashMap,SimpleType>(); static { for (int i = 0; i < typeArray.length; i++) { - final SimpleType type = typeArray[i]; + final SimpleType type = typeArray[i]; canonicalTypes.put(type, type); } } @@ -310,7 +310,7 @@ public final class SimpleType extends OpenType { * resolved. */ public Object readResolve() throws ObjectStreamException { - final SimpleType canonical = canonicalTypes.get(this); + final SimpleType canonical = canonicalTypes.get(this); if (canonical == null) { // Should not happen throw new InvalidObjectException("Invalid SimpleType: " + this); diff --git a/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java b/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java index 4e0c51cc9ba..faeba1a91e9 100644 --- a/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java +++ b/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java @@ -30,6 +30,7 @@ package javax.management.openmbean; // java import // import com.sun.jmx.mbeanserver.GetPropertyAction; +import com.sun.jmx.mbeanserver.Util; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; @@ -611,7 +612,7 @@ public class TabularDataSupport @SuppressWarnings("unchecked") // historical confusion about the return type public Collection values() { - return (Collection) dataMap.values() ; + return Util.cast(dataMap.values()); } @@ -647,7 +648,7 @@ public class TabularDataSupport @SuppressWarnings("unchecked") // historical confusion about the return type public Set> entrySet() { - return (Set) dataMap.entrySet(); + return Util.cast(dataMap.entrySet()); } @@ -725,8 +726,7 @@ public class TabularDataSupport if (this.size() != other.size()) { return false; } - for (Iterator iter = this.values().iterator(); iter.hasNext(); ) { - CompositeData value = (CompositeData) iter.next(); + for (CompositeData value : dataMap.values()) { if ( ! other.containsValue(value) ) { return false; } @@ -760,9 +760,8 @@ public class TabularDataSupport int result = 0; result += this.tabularType.hashCode(); - for (Iterator iter = this.values().iterator(); iter.hasNext(); ) { - result += ((CompositeData)iter.next()).hashCode(); - } + for (Object value : values()) + result += value.hashCode(); return result; diff --git a/jdk/src/share/classes/javax/management/openmbean/TabularType.java b/jdk/src/share/classes/javax/management/openmbean/TabularType.java index b45f2f661d5..8f953107539 100644 --- a/jdk/src/share/classes/javax/management/openmbean/TabularType.java +++ b/jdk/src/share/classes/javax/management/openmbean/TabularType.java @@ -237,7 +237,7 @@ public class TabularType extends OpenType { } @Override - boolean isAssignableFrom(OpenType ot) { + boolean isAssignableFrom(OpenType ot) { if (!(ot instanceof TabularType)) return false; TabularType tt = (TabularType) ot; @@ -329,9 +329,8 @@ public class TabularType extends OpenType { int value = 0; value += this.getTypeName().hashCode(); value += this.rowType.hashCode(); - for (Iterator k = indexNames.iterator(); k.hasNext(); ) { - value += k.next().hashCode(); - } + for (String index : indexNames) + value += index.hashCode(); myHashCode = Integer.valueOf(value); } @@ -364,12 +363,10 @@ public class TabularType extends OpenType { .append(",rowType=") .append(rowType.toString()) .append(",indexNames=("); - int i=0; - Iterator k = indexNames.iterator(); - while( k.hasNext() ) { - if (i > 0) result.append(","); - result.append(k.next().toString()); - i++; + String sep = ""; + for (String index : indexNames) { + result.append(sep).append(index); + sep = ","; } result.append("))"); myToString = result.toString(); diff --git a/jdk/src/share/classes/javax/management/relation/MBeanServerNotificationFilter.java b/jdk/src/share/classes/javax/management/relation/MBeanServerNotificationFilter.java index 3b1edc58a4d..fbbbf3d70c3 100644 --- a/jdk/src/share/classes/javax/management/relation/MBeanServerNotificationFilter.java +++ b/jdk/src/share/classes/javax/management/relation/MBeanServerNotificationFilter.java @@ -354,7 +354,7 @@ public class MBeanServerNotificationFilter extends NotificationFilterSupport { // Checks the type first String ntfType = notif.getType(); - Vector enabledTypes = getEnabledTypes(); + Vector enabledTypes = getEnabledTypes(); if (!(enabledTypes.contains(ntfType))) { RELATION_LOGGER.logp(Level.FINER, MBeanServerNotificationFilter.class.getName(), @@ -464,8 +464,8 @@ public class MBeanServerNotificationFilter extends NotificationFilterSupport { // Serializes this instance in the old serial form // ObjectOutputStream.PutField fields = out.putFields(); - fields.put("mySelectObjNameList", (Vector)selectedNames); - fields.put("myDeselectObjNameList", (Vector)deselectedNames); + fields.put("mySelectObjNameList", selectedNames); + fields.put("myDeselectObjNameList", deselectedNames); out.writeFields(); } else diff --git a/jdk/src/share/classes/javax/management/relation/RelationService.java b/jdk/src/share/classes/javax/management/relation/RelationService.java index 98a4809ea41..fcf0cb0127e 100644 --- a/jdk/src/share/classes/javax/management/relation/RelationService.java +++ b/jdk/src/share/classes/javax/management/relation/RelationService.java @@ -1111,7 +1111,7 @@ public class RelationService extends NotificationBroadcasterSupport throw new IllegalArgumentException(excMsg); } - if (!(oldValue instanceof ArrayList)) + if (!(oldValue instanceof ArrayList)) oldValue = new ArrayList(oldValue); RELATION_LOGGER.entering(RelationService.class.getName(), @@ -1881,7 +1881,7 @@ public class RelationService extends NotificationBroadcasterSupport "getRole", params, signature)); - if (invokeResult == null || invokeResult instanceof ArrayList) + if (invokeResult == null || invokeResult instanceof ArrayList) result = invokeResult; else result = new ArrayList(invokeResult); @@ -2786,7 +2786,7 @@ public class RelationService extends NotificationBroadcasterSupport // Note that it is possible that the MBean has already been removed // from the internal map: this is the case when the MBean is // unregistered, the role is updated, then we arrive here. - HashMap mbeanRefMap = (HashMap) + Map> mbeanRefMap = (myRefedMBeanObjName2RelIdsMap.get(objectName)); if (mbeanRefMap == null) { @@ -2796,11 +2796,11 @@ public class RelationService extends NotificationBroadcasterSupport return true; } - ArrayList roleNames = new ArrayList(); + List roleNames = null; if (!allRolesFlag) { // Now retrieves the roles of current relation where the MBean // was referenced - roleNames = (ArrayList)(mbeanRefMap.get(relationId)); + roleNames = mbeanRefMap.get(relationId); // Removes obsolete reference to role int obsRefIdx = roleNames.indexOf(roleName); @@ -2840,8 +2840,8 @@ public class RelationService extends NotificationBroadcasterSupport // // -exception RelationServiceNotRegisteredException if the Relation // Service is not registered in the MBean Server. - private void updateUnregistrationListener(List newRefList, - List obsoleteRefList) + private void updateUnregistrationListener(List newRefList, + List obsoleteRefList) throws RelationServiceNotRegisteredException { if (newRefList != null && obsoleteRefList != null) { @@ -2871,24 +2871,14 @@ public class RelationService extends NotificationBroadcasterSupport // Enables ObjectNames in newRefList if (newRefList != null) { - for (Iterator newRefIter = newRefList.iterator(); - newRefIter.hasNext();) { - - ObjectName newObjName = (ObjectName) - (newRefIter.next()); + for (ObjectName newObjName : newRefList) myUnregNtfFilter.enableObjectName(newObjName); - } } if (obsoleteRefList != null) { // Disables ObjectNames in obsoleteRefList - for (Iterator obsRefIter = obsoleteRefList.iterator(); - obsRefIter.hasNext();) { - - ObjectName obsObjName = (ObjectName) - (obsRefIter.next()); + for (ObjectName obsObjName : obsoleteRefList) myUnregNtfFilter.disableObjectName(obsObjName); - } } // Under test @@ -3047,18 +3037,13 @@ public class RelationService extends NotificationBroadcasterSupport // to see which roles have not been initialized // Note: no need to test if list not null before cloning, not allowed // to have an empty relation type. - ArrayList roleInfoList = (ArrayList) - (((ArrayList)(relType.getRoleInfos())).clone()); + List roleInfoList = new ArrayList(relType.getRoleInfos()); if (roleList != null) { - for (Iterator roleIter = roleList.iterator(); - roleIter.hasNext();) { - - Role currRole = (Role)(roleIter.next()); + for (Role currRole : roleList.asList()) { String currRoleName = currRole.getRoleName(); - ArrayList currRoleValue = (ArrayList) - (currRole.getRoleValue()); + List currRoleValue = currRole.getRoleValue(); // Retrieves corresponding role info // Can throw a RoleInfoNotFoundException to be converted into a // RoleNotFoundException @@ -3137,9 +3122,7 @@ public class RelationService extends NotificationBroadcasterSupport // Only role list parameter used, as default initialization of roles // done automatically in initializeMissingRoles() sets each // uninitialized role to an empty value. - for (Iterator roleIter = roleList.iterator(); - roleIter.hasNext();) { - Role currRole = (Role)(roleIter.next()); + for (Role currRole : roleList.asList()) { // Creates a dummy empty ArrayList of ObjectNames to be the old // role value :) List dummyList = new ArrayList(); @@ -3191,7 +3174,7 @@ public class RelationService extends NotificationBroadcasterSupport // -exception IllegalArgumentException if null parameter private Integer checkRoleInt(int chkType, String roleName, - List roleValue, + List roleValue, RoleInfo roleInfo, boolean writeChkFlag) throws IllegalArgumentException { @@ -3266,9 +3249,7 @@ public class RelationService extends NotificationBroadcasterSupport // registered in the same MBean Server. String expClassName = roleInfo.getRefMBeanClassName(); - for (Iterator refMBeanIter = roleValue.iterator(); - refMBeanIter.hasNext();) { - ObjectName currObjName = (ObjectName)(refMBeanIter.next()); + for (ObjectName currObjName : roleValue) { // Checks it is registered if (currObjName == null) { @@ -3330,7 +3311,7 @@ public class RelationService extends NotificationBroadcasterSupport ObjectName relationObjName, String relationId, String relationTypeName, - List roleInfoList) + List roleInfoList) throws IllegalArgumentException, RelationServiceNotRegisteredException, InvalidRoleValueException { @@ -3361,10 +3342,8 @@ public class RelationService extends NotificationBroadcasterSupport // with an empty list of ObjectNames. // A check is performed to verify that the role can be set to an // empty value, according to its minimum cardinality - for (Iterator roleInfoIter = roleInfoList.iterator(); - roleInfoIter.hasNext();) { + for (RoleInfo currRoleInfo : roleInfoList) { - RoleInfo currRoleInfo = (RoleInfo)(roleInfoIter.next()); String roleName = currRoleInfo.getName(); // Creates an empty value @@ -3663,7 +3642,7 @@ public class RelationService extends NotificationBroadcasterSupport // not exist in the relation private void handleReferenceUnregistration(String relationId, ObjectName objectName, - List roleNameList) + List roleNameList) throws IllegalArgumentException, RelationServiceNotRegisteredException, RelationNotFoundException, @@ -3694,14 +3673,12 @@ public class RelationService extends NotificationBroadcasterSupport // Flag to specify if the relation has to be deleted boolean deleteRelFlag = false; - for (Iterator roleNameIter = roleNameList.iterator(); - roleNameIter.hasNext();) { + for (String currRoleName : roleNameList) { if (deleteRelFlag) { break; } - String currRoleName = (String)(roleNameIter.next()); // Retrieves number of MBeans currently referenced in role // BEWARE! Do not use getRole() as role may be not readable // @@ -3753,10 +3730,7 @@ public class RelationService extends NotificationBroadcasterSupport // using setRole(). So the Relation Service will update the // myRefedMBeanObjName2RelIdsMap to refelect the new role // value! - for (Iterator roleNameIter = roleNameList.iterator(); - roleNameIter.hasNext();) { - - String currRoleName = (String)(roleNameIter.next()); + for (String currRoleName : roleNameList) { if (relObj instanceof RelationSupport) { // Internal relation diff --git a/jdk/src/share/classes/javax/management/relation/RelationSupport.java b/jdk/src/share/classes/javax/management/relation/RelationSupport.java index ed0958e9b4a..c714a3ecbaa 100644 --- a/jdk/src/share/classes/javax/management/relation/RelationSupport.java +++ b/jdk/src/share/classes/javax/management/relation/RelationSupport.java @@ -108,7 +108,7 @@ public class RelationSupport // via Relation Service setRole() and setRoles() methods // - if the relation is internal to the Relation Service, via // setRoleInt() and setRolesInt() methods. - private Map myRoleName2ValueMap = new HashMap(); + private final Map myRoleName2ValueMap = new HashMap(); // Flag to indicate if the object has been added in the Relation Service private final AtomicBoolean myInRelServFlg = new AtomicBoolean(); @@ -424,7 +424,7 @@ public class RelationSupport } } - ArrayList roleValue = (ArrayList)(role.getRoleValue()); + List roleValue = role.getRoleValue(); RELATION_LOGGER.exiting(RelationSupport.class.getName(), "getRoleCardinality"); @@ -855,8 +855,7 @@ public class RelationSupport // Note: no need to test if role value (list) not null before // cloning, null value not allowed, empty list if // nothing. - result = (ArrayList) - (((ArrayList)(role.getRoleValue())).clone()); + result = new ArrayList(role.getRoleValue()); } else { // Role retrieved during multi-role retrieval: returns the @@ -1492,10 +1491,7 @@ public class RelationSupport RoleList roleList = new RoleList(); RoleUnresolvedList roleUnresList = new RoleUnresolvedList(); - for (Iterator roleIter = list.iterator(); - roleIter.hasNext();) { - - Role currRole = (Role)(roleIter.next()); + for (Role currRole : list.asList()) { Object currResult = null; // Can throw: @@ -1617,12 +1613,10 @@ public class RelationSupport synchronized(myRoleName2ValueMap) { - for (Iterator roleIter = list.iterator(); - roleIter.hasNext();) { + for (Role currRole : list.asList()) { // No need to check if role is null, it is not allowed to store // a null role in a RoleList :) - Role currRole = (Role)(roleIter.next()); String currRoleName = currRole.getRoleName(); if (myRoleName2ValueMap.containsKey(currRoleName)) { diff --git a/jdk/src/share/classes/javax/management/relation/Role.java b/jdk/src/share/classes/javax/management/relation/Role.java index dc8f7944304..79fe1490a88 100644 --- a/jdk/src/share/classes/javax/management/relation/Role.java +++ b/jdk/src/share/classes/javax/management/relation/Role.java @@ -228,9 +228,9 @@ public class Role implements Serializable { public String toString() { StringBuilder result = new StringBuilder(); result.append("role name: " + name + "; role value: "); - for (Iterator objNameIter = objectNameList.iterator(); + for (Iterator objNameIter = objectNameList.iterator(); objNameIter.hasNext();) { - ObjectName currObjName = (ObjectName)(objNameIter.next()); + ObjectName currObjName = objNameIter.next(); result.append(currObjName.toString()); if (objNameIter.hasNext()) { result.append(", "); @@ -325,7 +325,7 @@ public class Role implements Serializable { // ObjectOutputStream.PutField fields = out.putFields(); fields.put("myName", name); - fields.put("myObjNameList", (ArrayList)objectNameList); + fields.put("myObjNameList", objectNameList); out.writeFields(); } else diff --git a/jdk/src/share/classes/javax/management/relation/RoleList.java b/jdk/src/share/classes/javax/management/relation/RoleList.java index a03ffe28065..467c3f45967 100644 --- a/jdk/src/share/classes/javax/management/relation/RoleList.java +++ b/jdk/src/share/classes/javax/management/relation/RoleList.java @@ -25,6 +25,7 @@ package javax.management.relation; +import com.sun.jmx.mbeanserver.Util; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -140,7 +141,7 @@ public class RoleList extends ArrayList { checkTypeSafe(this); typeSafe = true; } - return (List) (List) this; + return Util.cast(this); } // diff --git a/jdk/src/share/classes/javax/management/relation/RoleResult.java b/jdk/src/share/classes/javax/management/relation/RoleResult.java index 64df5b97ecb..6ea55250c40 100644 --- a/jdk/src/share/classes/javax/management/relation/RoleResult.java +++ b/jdk/src/share/classes/javax/management/relation/RoleResult.java @@ -172,7 +172,7 @@ public class RoleResult implements Serializable { roleList = new RoleList(); - for (Iterator roleIter = list.iterator(); + for (Iterator roleIter = list.iterator(); roleIter.hasNext();) { Role currRole = (Role)(roleIter.next()); roleList.add((Role)(currRole.clone())); @@ -195,7 +195,7 @@ public class RoleResult implements Serializable { unresolvedRoleList = new RoleUnresolvedList(); - for (Iterator roleUnresIter = unresolvedList.iterator(); + for (Iterator roleUnresIter = unresolvedList.iterator(); roleUnresIter.hasNext();) { RoleUnresolved currRoleUnres = (RoleUnresolved)(roleUnresIter.next()); diff --git a/jdk/src/share/classes/javax/management/relation/RoleUnresolved.java b/jdk/src/share/classes/javax/management/relation/RoleUnresolved.java index 8b25797488b..a20173c6f77 100644 --- a/jdk/src/share/classes/javax/management/relation/RoleUnresolved.java +++ b/jdk/src/share/classes/javax/management/relation/RoleUnresolved.java @@ -285,9 +285,9 @@ public class RoleUnresolved implements Serializable { result.append("role name: " + roleName); if (roleValue != null) { result.append("; value: "); - for (Iterator objNameIter = roleValue.iterator(); + for (Iterator objNameIter = roleValue.iterator(); objNameIter.hasNext();) { - ObjectName currObjName = (ObjectName)(objNameIter.next()); + ObjectName currObjName = objNameIter.next(); result.append(currObjName.toString()); if (objNameIter.hasNext()) { result.append(", "); @@ -344,7 +344,7 @@ public class RoleUnresolved implements Serializable { // ObjectOutputStream.PutField fields = out.putFields(); fields.put("myRoleName", roleName); - fields.put("myRoleValue", (ArrayList)roleValue); + fields.put("myRoleValue", roleValue); fields.put("myPbType", problemType); out.writeFields(); } diff --git a/jdk/src/share/classes/javax/management/relation/RoleUnresolvedList.java b/jdk/src/share/classes/javax/management/relation/RoleUnresolvedList.java index 3b4e42ebfc6..873028b4592 100644 --- a/jdk/src/share/classes/javax/management/relation/RoleUnresolvedList.java +++ b/jdk/src/share/classes/javax/management/relation/RoleUnresolvedList.java @@ -25,6 +25,7 @@ package javax.management.relation; +import com.sun.jmx.mbeanserver.Util; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -140,7 +141,7 @@ public class RoleUnresolvedList extends ArrayList { checkTypeSafe(this); typeSafe = true; } - return (List) (List) this; + return Util.cast(this); } // diff --git a/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java b/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java index 219865b603c..051d8b34c45 100644 --- a/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java +++ b/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java @@ -367,7 +367,8 @@ public class JMXConnectorFactory { return provider.newJMXConnector(serviceURL, fixedenv); } - private static String resolvePkgs(Map env) throws JMXProviderException { + private static String resolvePkgs(Map env) + throws JMXProviderException { Object pkgsObject = null; @@ -521,7 +522,7 @@ public class JMXConnectorFactory { return null; } - static ClassLoader resolveClassLoader(Map environment) { + static ClassLoader resolveClassLoader(Map environment) { ClassLoader loader = null; if (environment != null) { diff --git a/jdk/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java b/jdk/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java index a4c5fe0eadf..5c2970f2116 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java @@ -118,7 +118,8 @@ class NoCallStackClassLoader extends ClassLoader { * if it is one of the classes whose byte code we have, or * delegate the load if it is one of the referenced classes. */ - protected Class findClass(String name) throws ClassNotFoundException { + @Override + protected Class findClass(String name) throws ClassNotFoundException { for (int i = 0; i < classNames.length; i++) { if (name.equals(classNames[i])) { return defineClass(classNames[i], byteCodes[i], 0, diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnection.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnection.java index 863b3dca8cc..6fbafdb531a 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnection.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnection.java @@ -31,7 +31,6 @@ import java.rmi.MarshalledObject; import java.rmi.Remote; import java.util.Set; -import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.InstanceAlreadyExistsException; @@ -45,11 +44,11 @@ import javax.management.MBeanRegistrationException; import javax.management.MBeanServerConnection; import javax.management.NotCompliantMBeanException; -import javax.management.NotificationFilter; import javax.management.ObjectInstance; import javax.management.ObjectName; -import javax.management.QueryExp; import javax.management.ReflectionException; +import javax.management.RuntimeMBeanException; +import javax.management.RuntimeOperationsException; import javax.management.remote.NotificationResult; import javax.security.auth.Subject; @@ -89,8 +88,9 @@ import javax.security.auth.Subject; * even though it would add useful information to the documentation. The * reason is that it was only added in Mustang (Java SE 6), whereas versions * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our - * commitments for JSR 255. + * commitments for JSR 255. This is also why we suppress rawtypes warnings. */ +@SuppressWarnings("rawtypes") public interface RMIConnection extends Closeable, Remote { /** *

    Returns the connection ID. This string is different for diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java index a87d146e94e..acac5ec8f22 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java @@ -308,6 +308,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public ObjectInstance createMBean(String className, ObjectName name, MarshalledObject params, @@ -368,6 +369,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, @@ -493,6 +495,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public Set queryMBeans(ObjectName name, MarshalledObject query, @@ -527,6 +530,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public Set queryNames(ObjectName name, MarshalledObject query, @@ -668,6 +672,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public void setAttribute(ObjectName name, MarshalledObject attribute, Subject delegationSubject) @@ -720,6 +725,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public AttributeList setAttributes(ObjectName name, MarshalledObject attributes, Subject delegationSubject) @@ -765,6 +771,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public Object invoke(ObjectName name, String operationName, MarshalledObject params, @@ -928,6 +935,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public Integer[] addNotificationListeners(ObjectName[] names, MarshalledObject[] filters, Subject[] delegationSubjects) @@ -1013,6 +1021,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public void addNotificationListener(ObjectName name, ObjectName listener, MarshalledObject filter, @@ -1148,6 +1157,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } + @SuppressWarnings("rawtypes") // MarshalledObject public void removeNotificationListener(ObjectName name, ObjectName listener, MarshalledObject filter, @@ -1809,7 +1819,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { } } - private static T unwrap(final MarshalledObject mo, + private static T unwrap(final MarshalledObject mo, final ClassLoader cl, final Class wrappedClass) throws IOException { @@ -1847,7 +1857,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { return null; } - private static T unwrap(final MarshalledObject mo, + private static T unwrap(final MarshalledObject mo, final ClassLoader cl1, final ClassLoader cl2, final Class wrappedClass) diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java index 934dac790db..1f17143b948 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java @@ -28,6 +28,7 @@ package javax.management.remote.rmi; import com.sun.jmx.event.DaemonThreadFactory; import com.sun.jmx.event.EventConnection; import com.sun.jmx.mbeanserver.PerThreadGroupPool; +import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.internal.ClientCommunicatorAdmin; import com.sun.jmx.remote.internal.ClientListenerInfo; import com.sun.jmx.remote.internal.ClientNotifForwarder; @@ -584,7 +585,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable // added for re-connection private Integer addListenerWithSubject(ObjectName name, - MarshalledObject filter, + MarshalledObject filter, Subject delegationSubject, boolean reconnect) throws InstanceNotFoundException, IOException { @@ -595,7 +596,8 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable "(ObjectName,MarshalledObject,Subject)"); final ObjectName[] names = new ObjectName[] {name}; - final MarshalledObject[] filters = new MarshalledObject[] {filter}; + final MarshalledObject[] filters = + Util.cast(new MarshalledObject[] {filter}); final Subject[] delegationSubjects = new Subject[] { delegationSubject }; @@ -611,7 +613,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable // added for re-connection private Integer[] addListenersWithSubjects(ObjectName[] names, - MarshalledObject[] filters, + MarshalledObject[] filters, Subject[] delegationSubjects, boolean reconnect) throws InstanceNotFoundException, IOException { @@ -1362,7 +1364,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable //-------------------------------------------------------------------- private class RMINotifClient extends ClientNotifForwarder { - public RMINotifClient(ClassLoader cl, Map env) { + public RMINotifClient(ClassLoader cl, Map env) { super(cl, env); } @@ -1444,8 +1446,8 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable Integer[] listenerIDs; final ObjectName[] names = new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME}; - final MarshalledObject[] filters = - new MarshalledObject[] {sFilter}; + final MarshalledObject[] filters = + Util.cast(new MarshalledObject[] {sFilter}); final Subject[] subjects = new Subject[] {null}; try { listenerIDs = @@ -1580,7 +1582,8 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable final ObjectName[] names = new ObjectName[len]; final NotificationListener[] listeners = new NotificationListener[len]; final NotificationFilter[] filters = new NotificationFilter[len]; - final MarshalledObject[] mFilters = new MarshalledObject[len]; + final MarshalledObject[] mFilters = + Util.cast(new MarshalledObject[len]); final Object[] handbacks = new Object[len]; for (i=0;i environment) throws IOException { if (rmiServer instanceof javax.rmi.CORBA.Stub) { javax.rmi.CORBA.Stub stub = (javax.rmi.CORBA.Stub) rmiServer; @@ -1776,7 +1779,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable * does not point to an {@link org.omg.CORBA.ORB ORB}. * @exception IOException if the ORB initialization failed. **/ - static ORB resolveOrb(Map environment) + static ORB resolveOrb(Map environment) throws IOException { if (environment != null) { final Object orb = environment.get(EnvHelp.DEFAULT_ORB); @@ -2004,7 +2007,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable } } - private RMIServer findRMIServerIIOP(String ior, Map env, boolean isIiop) { + private RMIServer findRMIServerIIOP(String ior, Map env, boolean isIiop) { // could forbid "rmi:" URL here -- but do we need to? final ORB orb = (ORB) env.get(EnvHelp.DEFAULT_ORB); @@ -2012,7 +2015,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable return (RMIServer) PortableRemoteObject.narrow(stub, RMIServer.class); } - private RMIServer findRMIServerJRMP(String base64, Map env, boolean isIiop) + private RMIServer findRMIServerJRMP(String base64, Map env, boolean isIiop) throws IOException { // could forbid "iiop:" URL here -- but do we need to? final byte[] serialized; @@ -2046,7 +2049,8 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable this.loader = cl; } - protected Class resolveClass(ObjectStreamClass classDesc) + @Override + protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { return Class.forName(classDesc.getName(), false, loader); } @@ -2121,13 +2125,13 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable private static final String rmiServerImplStubClassName = RMIServer.class.getName() + "Impl_Stub"; - private static final Class rmiServerImplStubClass; + private static final Class rmiServerImplStubClass; private static final String rmiConnectionImplStubClassName = RMIConnection.class.getName() + "Impl_Stub"; private static final Class rmiConnectionImplStubClass; private static final String pRefClassName = "com.sun.jmx.remote.internal.PRef"; - private static final Constructor proxyRefConstructor; + private static final Constructor proxyRefConstructor; static { final String pRefByteCodeString = "\312\376\272\276\0\0\0.\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17\0"+ @@ -2162,7 +2166,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable } }; - Class serverStubClass; + Class serverStubClass; try { serverStubClass = Class.forName(rmiServerImplStubClassName); } catch (Exception e) { @@ -2175,10 +2179,10 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable rmiServerImplStubClass = serverStubClass; Class stubClass; - Constructor constr; + Constructor constr; try { stubClass = Class.forName(rmiConnectionImplStubClassName); - constr = (Constructor) AccessController.doPrivileged(action); + constr = (Constructor) AccessController.doPrivileged(action); } catch (Exception e) { logger.error("", "Failed to initialize proxy reference constructor "+ @@ -2198,9 +2202,8 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable RemoteRef ref = stub.getRef(); RemoteRef proxyRef = (RemoteRef) proxyRefConstructor.newInstance(new Object[] {ref}); - final Class[] constrTypes = {RemoteRef.class}; - final Constructor rmiConnectionImplStubConstructor = - rmiConnectionImplStubClass.getConstructor(constrTypes); + final Constructor rmiConnectionImplStubConstructor = + rmiConnectionImplStubClass.getConstructor(RemoteRef.class); Object[] args = {proxyRef}; RMIConnection proxyStub = (RMIConnection) rmiConnectionImplStubConstructor.newInstance(args); @@ -2328,7 +2331,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable "com.sun.jmx.remote.internal.ProxyStub"; private static final String pInputStreamClassName = "com.sun.jmx.remote.internal.PInputStream"; - private static final Class proxyStubClass; + private static final Class proxyStubClass; static { final String proxyStubByteCodeString = "\312\376\272\276\0\0\0.\0)\12\0\14\0\26\7\0\27\12\0\14\0\30\12"+ diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java index 2cbe315bfdd..e56020b4722 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java @@ -423,7 +423,7 @@ public class RMIConnectorServer extends JMXConnectorServer { try { if (tracing) logger.trace("start", "binding to " + jndiUrl); - final Hashtable usemap = EnvHelp.mapToHashtable(attributes); + final Hashtable usemap = EnvHelp.mapToHashtable(attributes); bind(jndiUrl, usemap, objref, rebind); @@ -555,7 +555,7 @@ public class RMIConnectorServer extends JMXConnectorServer { logger.trace("stop", "unbind from external directory: " + boundJndiUrl); - final Hashtable usemap = EnvHelp.mapToHashtable(attributes); + final Hashtable usemap = EnvHelp.mapToHashtable(attributes); InitialContext ctx = new InitialContext(usemap); @@ -655,7 +655,7 @@ public class RMIConnectorServer extends JMXConnectorServer { * @param rmiServer The object to bind in the registry * @param rebind true if the object must be rebound. **/ - void bind(String jndiUrl, Hashtable attributes, + void bind(String jndiUrl, Hashtable attributes, RMIServer rmiServer, boolean rebind) throws NamingException, MalformedURLException { // if jndiURL is not null, we nust bind the stub to a @@ -692,7 +692,8 @@ public class RMIConnectorServer extends JMXConnectorServer { * @param attributes A Map containing environment parameters, * built from the Map specified at this object creation. **/ - private void encodeStubInAddress(RMIServer rmiServer, Map attributes) + private void encodeStubInAddress( + RMIServer rmiServer, Map attributes) throws IOException { final String protocol, host; @@ -735,14 +736,16 @@ public class RMIConnectorServer extends JMXConnectorServer { /** * Returns the IOR of the given rmiServer. **/ - static String encodeStub(RMIServer rmiServer, Map env) throws IOException { + static String encodeStub( + RMIServer rmiServer, Map env) throws IOException { if (rmiServer instanceof javax.rmi.CORBA.Stub) return "/ior/" + encodeIIOPStub(rmiServer, env); else return "/stub/" + encodeJRMPStub(rmiServer, env); } - static String encodeJRMPStub(RMIServer rmiServer, Map env) + static String encodeJRMPStub( + RMIServer rmiServer, Map env) throws IOException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); @@ -752,7 +755,8 @@ public class RMIConnectorServer extends JMXConnectorServer { return byteArrayToBase64(bytes); } - static String encodeIIOPStub(RMIServer rmiServer, Map env) + static String encodeIIOPStub( + RMIServer rmiServer, Map env) throws IOException { try { javax.rmi.CORBA.Stub stub = @@ -767,7 +771,8 @@ public class RMIConnectorServer extends JMXConnectorServer { * Object that we will bind to the registry. * This object is a stub connected to our RMIServerImpl. **/ - private static RMIServer objectToBind(RMIServerImpl rmiServer, Map env) + private static RMIServer objectToBind( + RMIServerImpl rmiServer, Map env) throws IOException { return RMIConnector. connectStub((RMIServer)rmiServer.toStub(),env); diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java index bc15562f5eb..d87b1d0544b 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java @@ -75,7 +75,7 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { * to an empty Map. */ public RMIServerImpl(Map env) { - this.env = (env == null) ? Collections.EMPTY_MAP : env; + this.env = (env == null) ? Collections.emptyMap() : env; } void setRMIConnectorServer(RMIConnectorServer connServer) @@ -337,8 +337,9 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { synchronized (clientList) { dropDeadReferences(); - for (Iterator it = clientList.iterator(); it.hasNext(); ) { - WeakReference wr = (WeakReference) it.next(); + for (Iterator> it = clientList.iterator(); + it.hasNext(); ) { + WeakReference wr = it.next(); if (wr.get() == client) { it.remove(); break; @@ -417,9 +418,10 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { dropDeadReferences(), this will usually be the first element of the list, but a garbage collection could have happened in between. */ - for (Iterator it = clientList.iterator(); it.hasNext(); ) { - WeakReference wr = (WeakReference) it.next(); - RMIConnection client = (RMIConnection) wr.get(); + for (Iterator> it = clientList.iterator(); + it.hasNext(); ) { + WeakReference wr = it.next(); + RMIConnection client = wr.get(); it.remove(); if (client != null) { try { @@ -475,10 +477,10 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { buf.append("//").append(clientHost); buf.append(" "); if (subject != null) { - Set principals = subject.getPrincipals(); + Set principals = subject.getPrincipals(); String sep = ""; - for (Iterator it = principals.iterator(); it.hasNext(); ) { - Principal p = (Principal) it.next(); + for (Iterator it = principals.iterator(); it.hasNext(); ) { + Principal p = it.next(); String name = p.getName().replace(' ', '_').replace(';', ':'); buf.append(sep).append(name); sep = ";"; @@ -492,8 +494,9 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { private void dropDeadReferences() { synchronized (clientList) { - for (Iterator it = clientList.iterator(); it.hasNext(); ) { - WeakReference wr = (WeakReference) it.next(); + for (Iterator> it = clientList.iterator(); + it.hasNext(); ) { + WeakReference wr = it.next(); if (wr.get() == null) it.remove(); } @@ -522,7 +525,7 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { private MBeanServer mbeanServer; - private final Map env; + private final Map env; private RMIConnectorServer connServer; diff --git a/jdk/src/share/classes/javax/management/timer/Timer.java b/jdk/src/share/classes/javax/management/timer/Timer.java index ea4d0b24a2a..909a1bbb0e5 100644 --- a/jdk/src/share/classes/javax/management/timer/Timer.java +++ b/jdk/src/share/classes/javax/management/timer/Timer.java @@ -248,8 +248,7 @@ public class Timer extends NotificationBroadcasterSupport */ public synchronized MBeanNotificationInfo[] getNotificationInfo() { Set notifTypes = new TreeSet(); - for (Iterator it = timerTable.values().iterator(); it.hasNext(); ) { - Object[] entry = (Object[]) it.next(); + for (Object[] entry : timerTable.values()) { TimerNotification notif = (TimerNotification) entry[TIMER_NOTIF_INDEX]; notifTypes.add(notif.getType()); diff --git a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java index 2560d7fea75..286e7352f25 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -43,7 +43,7 @@ class ExchangeImpl { String method; URI uri; HttpConnection connection; - int reqContentLen; + long reqContentLen; long rspContentLen; /* raw streams which access the socket directly */ InputStream ris; @@ -79,7 +79,7 @@ class ExchangeImpl { ServerImpl server; ExchangeImpl ( - String m, URI u, Request req, int len, HttpConnection connection + String m, URI u, Request req, long len, HttpConnection connection ) throws IOException { this.req = req; this.reqHdrs = req.headers(); @@ -148,7 +148,7 @@ class ExchangeImpl { if (uis != null) { return uis; } - if (reqContentLen == -1) { + if (reqContentLen == -1L) { uis_orig = new ChunkedInputStream (this, ris); uis = uis_orig; } else { diff --git a/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java b/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java index 6d6c9587fba..1061fb1c039 100644 --- a/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java +++ b/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java @@ -37,21 +37,21 @@ import com.sun.net.httpserver.spi.*; */ class FixedLengthInputStream extends LeftOverInputStream { - private int remaining; + private long remaining; - FixedLengthInputStream (ExchangeImpl t, InputStream src, int len) { + FixedLengthInputStream (ExchangeImpl t, InputStream src, long len) { super (t, src); this.remaining = len; } protected int readImpl (byte[]b, int off, int len) throws IOException { - eof = (remaining == 0); + eof = (remaining == 0L); if (eof) { return -1; } if (len > remaining) { - len = remaining; + len = (int)remaining; } int n = in.read(b, off, len); if (n > -1) { @@ -65,7 +65,7 @@ class FixedLengthInputStream extends LeftOverInputStream { return 0; } int n = in.available(); - return n < remaining? n: remaining; + return n < remaining? n: (int)remaining; } public boolean markSupported () {return false;} diff --git a/jdk/src/share/classes/sun/net/httpserver/Request.java b/jdk/src/share/classes/sun/net/httpserver/Request.java index bdafe663c1b..8b50ad83a87 100644 --- a/jdk/src/share/classes/sun/net/httpserver/Request.java +++ b/jdk/src/share/classes/sun/net/httpserver/Request.java @@ -53,7 +53,7 @@ class Request { do { startLine = readLine(); /* skip blank lines */ - } while (startLine.equals ("")); + } while (startLine == null ? false : startLine.equals ("")); } diff --git a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java index a6d4b079763..cfff8dd0f6a 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java @@ -470,13 +470,13 @@ class ServerImpl implements TimeSource { String version = requestLine.substring (start); Headers headers = req.headers(); String s = headers.getFirst ("Transfer-encoding"); - int clen = 0; + long clen = 0L; if (s !=null && s.equalsIgnoreCase ("chunked")) { - clen = -1; + clen = -1L; } else { s = headers.getFirst ("Content-Length"); if (s != null) { - clen = Integer.parseInt (s); + clen = Long.parseLong(s); } } ctx = contexts.findContext (protocol, uri.getPath()); diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java index 05361fca444..3b5d8f74d27 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java @@ -272,14 +272,14 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { */ private Method[] getMemberMethods() { if (memberMethods == null) { - final Method[] mm = type.getDeclaredMethods(); - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - AccessibleObject.setAccessible(mm, true); - return null; - } - }); - memberMethods = mm; + memberMethods = AccessController.doPrivileged( + new PrivilegedAction() { + public Method[] run() { + final Method[] mm = type.getDeclaredMethods(); + AccessibleObject.setAccessible(mm, true); + return mm; + } + }); } return memberMethods; } diff --git a/jdk/test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java b/jdk/test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java new file mode 100644 index 00000000000..76a71fc120b --- /dev/null +++ b/jdk/test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java @@ -0,0 +1,172 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6756771 + * @summary com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig + */ + +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.InetSocketAddress; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.Socket; +import java.util.logging.*; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +public class FixedLengthInputStream +{ + static final long POST_SIZE = 4L * 1024L * 1024L * 1024L; // 4Gig + + /* Remove when CR 6755625 is fixed */ + static final String requestHeaders = ((new StringBuilder()) + .append("POST /flis/ HTTP/1.1\r\n") + .append("User-Agent: Java/1.7.0\r\n") + .append("Host: localhost\r\n") + .append("Accept: text/html, image/gif, image/jpeg,") + .append( " *; q=.2, */*; q=.2\r\n") + .append("Content-Length: 4294967296\r\n\r\n")).toString(); + + void test(String[] args) throws IOException { + HttpServer httpServer = startHttpServer(); + int port = httpServer.getAddress().getPort(); + try { + /* Uncomment & when CR 6755625 is fixed, remove socket code + URL url = new URL("http://localhost:" + port + "/flis/"); + HttpURLConnection uc = (HttpURLConnection)url.openConnection(); + uc.setDoOutput(true); + uc.setRequestMethod("POST"); + uc.setFixedLengthStreamingMode(POST_SIZE); + OutputStream os = uc.getOutputStream(); + */ + + Socket socket = new Socket("localhost", port); + OutputStream os = socket.getOutputStream(); + PrintStream ps = new PrintStream(os); + debug("Request: " + requestHeaders); + ps.print(requestHeaders); + ps.flush(); + + /* create a 32K byte array with data to POST */ + int thirtyTwoK = 32 * 1024; + byte[] ba = new byte[thirtyTwoK]; + for (int i =0; i k = new Object(){}.getClass().getEnclosingClass(); + try {k.getMethod("instanceMain",String[].class) + .invoke( k.newInstance(), (Object) args);} + catch (Throwable e) {throw e.getCause();}} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + +} diff --git a/jdk/test/java/lang/annotation/ParameterAnnotations.java b/jdk/test/java/lang/annotation/ParameterAnnotations.java new file mode 100644 index 00000000000..fa02e53dfa6 --- /dev/null +++ b/jdk/test/java/lang/annotation/ParameterAnnotations.java @@ -0,0 +1,118 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6761678 + * @summary Check properties of Annotations returned from + * getParameterAnnotations, including freedom from security + * exceptions. + * @author Martin Buchholz + */ + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.security.Permission; +import java.security.Policy; +import java.security.ProtectionDomain; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@interface Named { + String value(); +} + +public class ParameterAnnotations { + + // A security policy that differs from the default only in that it + // allows a security manager to be uninstalled. + static class MyPolicy extends Policy { + final Policy defaultPolicy; + MyPolicy(Policy defaultPolicy) { + this.defaultPolicy = defaultPolicy; + } + public boolean implies(ProtectionDomain pd, Permission p) { + return p.getName().equals("setSecurityManager") || + defaultPolicy.implies(pd, p); + } + } + + public void nop(@Named("foo") Object foo, + @Named("bar") Object bar) { + } + + void test(String[] args) throws Throwable { + // Test without a security manager + test1(); + + // Test with a security manager + Policy defaultPolicy = Policy.getPolicy(); + Policy.setPolicy(new MyPolicy(defaultPolicy)); + System.setSecurityManager(new SecurityManager()); + try { + test1(); + } finally { + System.setSecurityManager(null); + Policy.setPolicy(defaultPolicy); + } + } + + void test1() throws Throwable { + for (Method m : thisClass.getMethods()) { + if (m.getName().equals("nop")) { + Annotation[][] ann = m.getParameterAnnotations(); + equal(ann.length, 2); + Annotation foo = ann[0][0]; + Annotation bar = ann[1][0]; + equal(foo.toString(), "@Named(value=foo)"); + equal(bar.toString(), "@Named(value=bar)"); + check(foo.equals(foo)); + check(! foo.equals(bar)); + } + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + static Class thisClass = new Object(){}.getClass().getEnclosingClass(); + public static void main(String[] args) throws Throwable { + try {thisClass.getMethod("instanceMain",String[].class) + .invoke(thisClass.newInstance(), (Object) args);} + catch (Throwable e) {throw e.getCause();}} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/javax/management/MBeanServer/MBeanExceptionTest.java b/jdk/test/javax/management/MBeanServer/MBeanExceptionTest.java index 25260e0c15e..3516953d750 100644 --- a/jdk/test/javax/management/MBeanServer/MBeanExceptionTest.java +++ b/jdk/test/javax/management/MBeanServer/MBeanExceptionTest.java @@ -23,16 +23,19 @@ /* * @test - * @bug 5035217 + * @bug 5035217 6766173 * @summary Test that MBean's RuntimeException is wrapped in * RuntimeMBeanException and (for Standard MBeans) that checked exceptions * are wrapped in MBeanException * @author Eamonn McManus - * @compile -source 1.4 MBeanExceptionTest.java + * @compile MBeanExceptionTest.java * @run main MBeanExceptionTest */ +import java.util.Collections; +import java.util.Set; import javax.management.*; +import javax.management.namespace.MBeanServerSupport; public class MBeanExceptionTest { public static void main(String[] args) throws Exception { @@ -56,6 +59,53 @@ public class MBeanExceptionTest { failures += test(mbs, standardName, true); failures += test(mbs, standardMBeanName, true); failures += test(mbs, dynamicName, false); + + final boolean[] booleans = {false, true}; + + for (boolean mbss : booleans) { + for (boolean runtimeX : booleans) { + Class excC = + runtimeX ? RuntimeMBeanException.class : MBeanException.class; + String excS = + runtimeX ? "a RuntimeMBeanException" : "an MBeanException"; + String mbsS = + mbss ? "a conformant MBeanServerSupport" : "a plain MBeanServer"; + MBeanServer xmbs = + mbss ? new CreateExceptionMBS() : mbs; + System.out.println( + "Test that, with " + mbsS + ", " + excS + " is wrapped " + + "in " + excS); + // E.g. "Test that, with a plain MBeanServer, an MBeanException + // is wrapped in an MBeanException". + try { + mbs.createMBean( + Except.class.getName(), new ObjectName(":name=Oops"), + new Object[] {runtimeX}, + new String[] {boolean.class.getName()}); + System.out.println( + "FAIL: createMBean succeeded but should not have"); + failures++; + } catch (Exception e) { + if (!excC.isInstance(e)) { + System.out.println( + "FAIL: expected " + excC.getName() + " from " + + "createMBean, got " + e); + failures++; + } else { + Throwable cause = e.getCause(); + if (!excC.isInstance(cause)) { + System.out.println( + "FAIL: expected " + excC.getName() + + " as cause of " + excC.getName() + + ", got " + e); + failures++; + } else + System.out.println("...ok"); + } + } + } + } + if (failures == 0) System.out.println("Test passed"); else { @@ -153,6 +203,15 @@ public class MBeanExceptionTest { } public static class Except implements ExceptMBean { + public Except() {} + + public Except(boolean runtimeX) throws MBeanException { + if (runtimeX) + throw new RuntimeMBeanException(new RuntimeException(), "Bang"); + else + throw new MBeanException(new Exception(), "Bang"); + } + public String getUncheckedException() { throw theUncheckedException; } @@ -221,4 +280,28 @@ public class MBeanExceptionTest { private static final RuntimeException theUncheckedException = new UnsupportedOperationException("The unchecked exception " + "that should be seen"); + + private static class CreateExceptionMBS extends MBeanServerSupport { + @Override + protected Set getNames() { + return Collections.emptySet(); + } + + @Override + public DynamicMBean getDynamicMBeanFor(ObjectName name) + throws InstanceNotFoundException { + throw new InstanceNotFoundException(name); + } + + @Override + public ObjectInstance createMBean(String className, + ObjectName name, ObjectName loaderName, Object[] params, + String[] signature, boolean useCLR) + throws ReflectionException, InstanceAlreadyExistsException, + MBeanRegistrationException, MBeanException, + NotCompliantMBeanException, InstanceNotFoundException { + Exception wrapped = new MBeanException(new Exception(), "Bang"); + throw new MBeanException(wrapped, "Bang"); + } + } } diff --git a/jdk/test/javax/management/eventService/CustomForwarderTest.java b/jdk/test/javax/management/eventService/CustomForwarderTest.java index 22238b37505..c9c866aaee0 100644 --- a/jdk/test/javax/management/eventService/CustomForwarderTest.java +++ b/jdk/test/javax/management/eventService/CustomForwarderTest.java @@ -23,7 +23,7 @@ /* * @test CustomForwarderTest - * @bug 5108776 + * @bug 5108776 6759619 * @summary Test that a custom EventForwarder can be added * @author Eamonn McManus */ @@ -45,6 +45,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import javax.management.MBeanNotificationInfo; import javax.management.MBeanServer; import javax.management.MBeanServerInvocationHandler; import javax.management.Notification; @@ -107,6 +108,14 @@ public class CustomForwarderTest { socket.close(); } + void simulateNonFatal() { + receiver.nonFatal(new Exception("NonFatal")); + } + + void simulateFailed() { + receiver.failed(new Error("Failed")); + } + private class Receiver implements Runnable { public void run() { byte[] buf = new byte[1024]; @@ -216,16 +225,26 @@ public class CustomForwarderTest { EventClientDelegateMBean.OBJECT_NAME, EventClientDelegateMBean.class, false); - EventRelay relay = new UdpEventRelay(delegate); + UdpEventRelay relay = new UdpEventRelay(delegate); EventClient client = new EventClient(delegate, relay, null, null, 0L); final Semaphore lostCountSema = new Semaphore(0); + final BlockingQueue nonFatalNotifs = + new ArrayBlockingQueue(1); + final BlockingQueue failedNotifs = + new ArrayBlockingQueue(1); NotificationListener lostListener = new NotificationListener() { public void handleNotification(Notification notification, Object handback) { if (notification.getType().equals(EventClient.NOTIFS_LOST)) { System.out.println("Got lost-notifs notif: count=" + notification.getUserData()); lostCountSema.release(((Long) notification.getUserData()).intValue()); + } else if (notification.getType().equals(EventClient.NONFATAL)) { + System.out.println("Got nonFatal notif"); + nonFatalNotifs.add(notification); + } else if (notification.getType().equals(EventClient.FAILED)) { + System.out.println("Got failed notif"); + failedNotifs.add(notification); } else System.out.println("Mysterious EventClient notif: " + notification); } @@ -300,6 +319,35 @@ public class CustomForwarderTest { Thread.sleep(10); assertEquals("Further lost-notifs", 0, lostCountSema.availablePermits()); + System.out.println("Testing error notifs"); + relay.simulateNonFatal(); + n = nonFatalNotifs.poll(10, TimeUnit.SECONDS); + assertEquals("Exception message for non-fatal exception", "NonFatal", + ((Throwable) n.getSource()).getMessage()); + relay.simulateFailed(); + n = failedNotifs.poll(10, TimeUnit.SECONDS); + assertEquals("Exception message for failed exception", "Failed", + ((Throwable) n.getSource()).getMessage()); + + // 6759619 + System.out.println("Test EventClient.getEventClientNotificationInfo"); + MBeanNotificationInfo[] mbnis = client.getEventClientNotificationInfo(); + final String[] expectedTypes = { + EventClient.NOTIFS_LOST, EventClient.NONFATAL, EventClient.FAILED + }; + check: + for (String type : expectedTypes) { + for (MBeanNotificationInfo mbni : mbnis) { + for (String t : mbni.getNotifTypes()) { + if (type.equals(t)) { + System.out.println("...found " + type); + continue check; + } + } + } + throw new Exception("TEST FAILED: Did not find notif type " + type); + } + client.close(); System.out.println("TEST PASSED"); diff --git a/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java b/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java new file mode 100644 index 00000000000..d44e289efd8 --- /dev/null +++ b/jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java @@ -0,0 +1,237 @@ +/* + * @test + * @bug 6713777 + * @summary Test that exception messages include all relevant information + * @author Eamonn McManus + */ + +import java.beans.ConstructorProperties; +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; + +public class ExceptionDiagnosisTest { + private static volatile String failure; + + // ------ Illegal MXBeans ------ + + // Test that all of BdelloidMXBean, Rotifer, and File appear in the + // exception messages. File is not an allowed type because of recursive + // getters like "File getParentFile()". + public static interface BdelloidMXBean { + public Rotifer getRotifer(); + } + + public static class Bdelloid implements BdelloidMXBean { + public Rotifer getRotifer() { + return null; + } + } + + public static class Rotifer { + public File getFile() { + return null; + } + } + + // Test that all of IndirectHashMapMXBean, HashMapContainer, and + // HashMap appear in the exception messages. + // HashMap is not an allowed type because only the + // java.util interface such as Map are allowed with generic parameters, + // not their concrete implementations like HashMap. + public static interface IndirectHashMapMXBean { + public HashMapContainer getContainer(); + } + + public static class IndirectHashMap implements IndirectHashMapMXBean { + public HashMapContainer getContainer() { + return null; + } + } + + public static class HashMapContainer { + public HashMap getHashMap() {return null;} + } + + // ------ MXBeans that are legal but where proxies are not ------ + + // Test that all of BlimMXBean, BlimContainer, Blim, and Blam appear + // in the exception messages for a proxy for this MXBean. Blam is + // legal in MXBeans but is not reconstructible so you cannot make + // a proxy for BlimMXBean. + public static interface BlimMXBean { + public BlimContainer getBlimContainer(); + } + + public static class BlimImpl implements BlimMXBean { + public BlimContainer getBlimContainer() { + return null; + } + } + + public static class BlimContainer { + public Blim getBlim() {return null;} + public void setBlim(Blim blim) {} + } + + public static class Blim { + public Blam getBlam() {return null;} + public void setBlam(Blam blam) {} + } + + public static class Blam { + public Blam(int x) {} + + public int getX() {return 0;} + } + + + // ------ Property name differing only in case ------ + + public static interface CaseProbMXBean { + public CaseProb getCaseProb(); + } + + public static class CaseProbImpl implements CaseProbMXBean { + public CaseProb getCaseProb() {return null;} + } + + public static class CaseProb { + @ConstructorProperties({"urlPath"}) + public CaseProb(String urlPath) {} + + public String getURLPath() {return null;} + } + + + public static void main(String[] args) throws Exception { + testMXBeans(new Bdelloid(), BdelloidMXBean.class, Rotifer.class, File.class); + testMXBeans(new IndirectHashMap(), + IndirectHashMapMXBean.class, HashMapContainer.class, + HashMapContainer.class.getMethod("getHashMap").getGenericReturnType()); + + testProxies(new BlimImpl(), BlimMXBean.class, BlimMXBean.class, + BlimContainer.class, Blim.class, Blam.class); + + testCaseProb(); + + if (failure == null) + System.out.println("TEST PASSED"); + else + throw new Exception("TEST FAILED: " + failure); + } + + private static void testMXBeans(Object mbean, Type... expectedTypes) + throws Exception { + try { + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + ObjectName name = new ObjectName("a:b=c"); + mbs.registerMBean(mbean, name); + fail("No exception from registerMBean for " + mbean); + } catch (NotCompliantMBeanException e) { + checkExceptionChain("MBean " + mbean, e, expectedTypes); + } + } + + private static void testProxies( + Object mbean, Class mxbeanClass, Type... expectedTypes) + throws Exception { + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + ObjectName name = new ObjectName("a:b=c"); + mbs.registerMBean(mbean, name); + T proxy = JMX.newMXBeanProxy(mbs, name, mxbeanClass); + List methods = new ArrayList(); + for (Method m : mxbeanClass.getMethods()) { + if (m.getDeclaringClass() == mxbeanClass) + methods.add(m); + } + if (methods.size() != 1) { + fail("TEST BUG: expected to find exactly one method in " + + mxbeanClass.getName() + ": " + methods); + } + Method getter = methods.get(0); + try { + try { + getter.invoke(proxy); + fail("No exception from proxy method " + getter.getName() + + " in " + mxbeanClass.getName()); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof Exception) + throw (Exception) cause; + else + throw (Error) cause; + } + } catch (IllegalArgumentException e) { + checkExceptionChain( + "Proxy for " + mxbeanClass.getName(), e, expectedTypes); + } + } + + private static void testCaseProb() throws Exception { + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + ObjectName name = new ObjectName("a:b=c"); + Object mbean = new CaseProbImpl(); + mbs.registerMBean(new CaseProbImpl(), name); + CaseProbMXBean proxy = JMX.newMXBeanProxy(mbs, name, CaseProbMXBean.class); + try { + CaseProb prob = proxy.getCaseProb(); + fail("No exception from proxy method getCaseProb"); + } catch (IllegalArgumentException e) { + String messageChain = messageChain(e); + if (messageChain.contains("URLPath")) { + System.out.println("Message chain contains URLPath as required: " + + messageChain); + } else { + fail("Exception chain for CaseProb does not mention property" + + " URLPath differing only in case"); + System.out.println("Full stack trace:"); + e.printStackTrace(System.out); + } + } + } + + private static void checkExceptionChain( + String what, Throwable e, Type[] expectedTypes) { + System.out.println("Exceptions in chain for " + what + ":"); + for (Throwable t = e; t != null; t = t.getCause()) + System.out.println(".." + t); + + String messageChain = messageChain(e); + + // Now check that each of the classes is mentioned in those messages + for (Type type : expectedTypes) { + String name = (type instanceof Class) ? + ((Class) type).getName() : type.toString(); + if (!messageChain.contains(name)) { + fail("Exception chain for " + what + " does not mention " + + name); + System.out.println("Full stack trace:"); + e.printStackTrace(System.out); + } + } + + System.out.println(); + } + + private static String messageChain(Throwable t) { + String msg = "//"; + for ( ; t != null; t = t.getCause()) + msg += " " + t.getMessage() + " //"; + return msg; + } + + private static void fail(String why) { + failure = why; + System.out.println("FAIL: " + why); + } +} diff --git a/jdk/test/javax/management/mxbean/TypeNameTest.java b/jdk/test/javax/management/mxbean/TypeNameTest.java index f5f48bccacb..b8189691c0b 100644 --- a/jdk/test/javax/management/mxbean/TypeNameTest.java +++ b/jdk/test/javax/management/mxbean/TypeNameTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6757225 + * @bug 6757225 6763051 * @summary Test that type names in MXBeans match their spec. * @author Eamonn McManus */ @@ -40,6 +40,8 @@ import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.StandardMBean; +import javax.management.openmbean.TabularData; +import javax.management.openmbean.TabularType; public class TypeNameTest { public static interface TestMXBean { @@ -63,7 +65,7 @@ public class TypeNameTest { } }; - static String failure; + static volatile String failure; public static void main(String[] args) throws Exception { TestMXBean testImpl = (TestMXBean) Proxy.newProxyInstance( @@ -74,24 +76,46 @@ public class TypeNameTest { mbs.registerMBean(mxbean, name); MBeanInfo mbi = mbs.getMBeanInfo(name); MBeanAttributeInfo[] mbais = mbi.getAttributes(); + boolean sawTabular = false; for (MBeanAttributeInfo mbai : mbais) { String attrName = mbai.getName(); String attrTypeName = (String) mbai.getDescriptor().getFieldValue("originalType"); String fieldName = attrName + "Name"; Field nameField = TestMXBean.class.getField(fieldName); String expectedTypeName = (String) nameField.get(null); + if (expectedTypeName.equals(attrTypeName)) { System.out.println("OK: " + attrName + ": " + attrTypeName); } else { - failure = "For attribute " + attrName + " expected type name \"" + + fail("For attribute " + attrName + " expected type name \"" + expectedTypeName + "\", found type name \"" + attrTypeName + - "\""; - System.out.println("FAIL: " + failure); + "\""); + } + + if (mbai.getType().equals(TabularData.class.getName())) { + sawTabular = true; + TabularType tt = (TabularType) mbai.getDescriptor().getFieldValue("openType"); + if (tt.getTypeName().equals(attrTypeName)) { + System.out.println("OK: TabularType name for " + attrName); + } else { + fail("For attribute " + attrName + " expected TabularType " + + "name \"" + attrTypeName + "\", found \"" + + tt.getTypeName()); + } } } + + if (!sawTabular) + fail("Test bug: did not test TabularType name"); + if (failure == null) System.out.println("TEST PASSED"); else throw new Exception("TEST FAILED: " + failure); } + + private static void fail(String why) { + System.out.println("FAIL: " + why); + failure = why; + } }