This commit is contained in:
J. Duke 2017-07-05 16:43:41 +02:00
commit 0f58116e47
184 changed files with 4690 additions and 1462 deletions

View File

@ -13,3 +13,4 @@ bb1ef4ee3d2c8cbf43a37d372325a7952be590b9 jdk7-b33
4b4f5fea8d7d0743f0c30d91fcd9bf9d96e5d2ad jdk7-b36 4b4f5fea8d7d0743f0c30d91fcd9bf9d96e5d2ad jdk7-b36
744554f5a3290e11c71cd2ddb1aff49e431f9ed0 jdk7-b37 744554f5a3290e11c71cd2ddb1aff49e431f9ed0 jdk7-b37
cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38 cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38
ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39

View File

@ -13,3 +13,4 @@ ef6af34d75a7b44e77083f1d4ee47631fa09d3b4 jdk7-b31
0723891eb8d1c27e67c54163af0b4cea05a4e036 jdk7-b36 0723891eb8d1c27e67c54163af0b4cea05a4e036 jdk7-b36
59d5848bdedebe91cc2753acce78911bcb4a66db jdk7-b37 59d5848bdedebe91cc2753acce78911bcb4a66db jdk7-b37
08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38 08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38
55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39

View File

@ -13,3 +13,4 @@ b727c32788a906c04839516ae7443a085185a300 jdk7-b32
e91159f921a58af3698e6479ea1fc5818da66d09 jdk7-b36 e91159f921a58af3698e6479ea1fc5818da66d09 jdk7-b36
9ee9cf798b59e7d51f8c0a686959f313867a55d6 jdk7-b37 9ee9cf798b59e7d51f8c0a686959f313867a55d6 jdk7-b37
d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38 d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38
49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2008
HS_MAJOR_VER=14 HS_MAJOR_VER=14
HS_MINOR_VER=0 HS_MINOR_VER=0
HS_BUILD_NUMBER=06 HS_BUILD_NUMBER=07
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=7 JDK_MINOR_VER=7

View File

@ -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, Label& done, Label* slow_case,
BiasedLockingCounters* counters) { BiasedLockingCounters* counters) {
assert(UseBiasedLocking, "why call this otherwise?"); 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, markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place,
mark_reg); mark_reg);
or3(G2_thread, mark_reg, temp_reg); or3(G2_thread, mark_reg, temp_reg);
casx_under_lock(mark_addr.base(), mark_reg, temp_reg, casn(mark_addr.base(), mark_reg, temp_reg);
(address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
// If the biasing toward our thread failed, this means that // If the biasing toward our thread failed, this means that
// another thread succeeded in biasing it toward itself and we // another thread succeeded in biasing it toward itself and we
// need to revoke that bias. The revocation will occur in the // 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); 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); 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); or3(G2_thread, temp_reg, temp_reg);
casx_under_lock(mark_addr.base(), mark_reg, temp_reg, casn(mark_addr.base(), mark_reg, temp_reg);
(address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
// If the biasing toward our thread failed, this means that // If the biasing toward our thread failed, this means that
// another thread succeeded in biasing it toward itself and we // another thread succeeded in biasing it toward itself and we
// need to revoke that bias. The revocation will occur in the // 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. // bits in this situation. Should attempt to preserve them.
load_klass(obj_reg, temp_reg); 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); 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, casn(mark_addr.base(), mark_reg, temp_reg);
(address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
// Fall through to the normal CAS-based lock, because no matter what // Fall through to the normal CAS-based lock, because no matter what
// the result of the above CAS, some thread must have succeeded in // the result of the above CAS, some thread must have succeeded in
// removing the bias bit from the object's header. // 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). // effect).
void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch, void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
BiasedLockingCounters* counters) { Register Rbox, Register Rscratch,
BiasedLockingCounters* counters,
bool try_bias) {
Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes()); Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes());
verify_oop(Roop); verify_oop(Roop);
@ -2838,7 +2838,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Registe
// Fetch object's markword // Fetch object's markword
ld_ptr(mark_addr, Rmark); ld_ptr(mark_addr, Rmark);
if (UseBiasedLocking) { if (try_bias) {
biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); 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 ld_ptr (mark_addr, Rmark); // fetch obj->mark
// Triage: biased, stack-locked, neutral, inflated // Triage: biased, stack-locked, neutral, inflated
if (UseBiasedLocking) { if (try_bias) {
biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters);
// Invariant: if control reaches this point in the emitted stream // Invariant: if control reaches this point in the emitted stream
// then Rmark has not been modified. // 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 ld_ptr (mark_addr, Rmark); // fetch obj->mark
// Triage: biased, stack-locked, neutral, inflated // Triage: biased, stack-locked, neutral, inflated
if (UseBiasedLocking) { if (try_bias) {
biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters);
// Invariant: if control reaches this point in the emitted stream // Invariant: if control reaches this point in the emitted stream
// then Rmark has not been modified. // then Rmark has not been modified.
@ -3039,7 +3039,9 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, Registe
bind (done) ; 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()); Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes());
Label done ; Label done ;
@ -3050,7 +3052,7 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, Regis
} }
if (EmitSync & 8) { if (EmitSync & 8) {
if (UseBiasedLocking) { if (try_bias) {
biased_locking_exit(mark_addr, Rscratch, done); biased_locking_exit(mark_addr, Rscratch, done);
} }
@ -3077,7 +3079,7 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, Regis
// I$ effects. // I$ effects.
Label LStacked ; Label LStacked ;
if (UseBiasedLocking) { if (try_bias) {
// TODO: eliminate redundant LDs of obj->mark // TODO: eliminate redundant LDs of obj->mark
biased_locking_exit(mark_addr, Rscratch, done); biased_locking_exit(mark_addr, Rscratch, done);
} }

View File

@ -2220,9 +2220,13 @@ class MacroAssembler: public Assembler {
// These set the icc condition code to equal if the lock succeeded // These set the icc condition code to equal if the lock succeeded
// and notEqual if it failed and requires a slow case // and notEqual if it failed and requires a slow case
void compiler_lock_object(Register Roop, Register Rmark, Register Rbox, Register Rscratch, void compiler_lock_object(Register Roop, Register Rmark, Register Rbox,
BiasedLockingCounters* counters = NULL); Register Rscratch,
void compiler_unlock_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 // Biased locking support
// Upon entry, lock_reg must point to the lock record on the stack, // Upon entry, lock_reg must point to the lock record on the stack,

View File

@ -906,7 +906,7 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
// load next super to check // load next super to check
if (UseCompressedOops) { 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 // Bump array pointer forward one oop
add( Rtmp2, 4, Rtmp2 ); add( Rtmp2, 4, Rtmp2 );
} else { } else {

View File

@ -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 g1_regL(R_G1H,R_G1);
reg_class g3_regL(R_G3H,R_G3);
reg_class o2_regL(R_O2H,R_O2); reg_class o2_regL(R_O2H,R_O2);
reg_class o7_regL(R_O7H,R_O7); 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 // NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0. // 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; return false;
} }
@ -1926,18 +1927,23 @@ encode %{
$mem$$base, $mem$$disp, $mem$$index, $dst$$reg); $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) %{ 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); $mem$$base, $mem$$disp, $mem$$index, $dst$$reg, Assembler::ASI_PRIMARY_LITTLE);
%} %}
enc_class form3_mem_prefetch_read( memory mem ) %{ 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*/); $mem$$base, $mem$$disp, $mem$$index, 0/*prefetch function many-reads*/);
%} %}
enc_class form3_mem_prefetch_write( memory mem ) %{ 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*/); $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 ), "need disp and disp+4" );
assert( Assembler::is_simm13($mem$$disp+4), "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?"); 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, -1, $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, R_G0_enc, $reg$$reg );
emit3_simm13( cbuf, Assembler::arith_op, $reg$$reg, Assembler::sllx_op3, $reg$$reg, 0x1020 ); 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 ); 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" ); assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" );
guarantee($mem$$index == R_G0_enc, "double index?"); guarantee($mem$$index == R_G0_enc, "double index?");
// Load long with 2 instructions // 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, -1, $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+4, R_G0_enc, $reg$$reg+1 );
%} %}
//%%% form3_mem_plus_4_reg is a hack--get rid of it //%%% form3_mem_plus_4_reg is a hack--get rid of it
enc_class form3_mem_plus_4_reg( memory mem, iRegI dst ) %{ enc_class form3_mem_plus_4_reg( memory mem, iRegI dst ) %{
guarantee($mem$$disp, "cannot offset a reg-reg operand by 4"); 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 ) %{ 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 != Rscratch, "");
assert(Rbox != Rmark, ""); 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) %{ 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 != Rscratch, "");
assert(Rbox != Rmark, ""); 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 ) %{ 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: // casx_under_lock picks 1 of 3 encodings:
// For 32-bit pointers you get a 32-bit CAS // For 32-bit pointers you get a 32-bit CAS
// For 64-bit pointers you get a 64-bit CASX // For 64-bit pointers you get a 64-bit CASX
__ casx_under_lock(Rmem, Rold, Rnew, // Swap(*Rmem,Rnew) if *Rmem == Rold __ casn(Rmem, Rold, Rnew); // Swap(*Rmem,Rnew) if *Rmem == Rold
(address) StubRoutines::Sparc::atomic_memory_operation_lock_addr());
__ cmp( Rold, Rnew ); __ cmp( Rold, Rnew );
%} %}
@ -3761,6 +3766,14 @@ operand g1RegL() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
operand g3RegL() %{
constraint(ALLOC_IN_RC(g3_regL));
match(iRegL);
format %{ %}
interface(REG_INTER);
%}
// Int Register safe // Int Register safe
// This is 64bit safe // This is 64bit safe
operand iRegIsafe() %{ operand iRegIsafe() %{
@ -5062,7 +5075,7 @@ instruct stkI_to_regF(regF dst, stackSlotI src) %{
size(4); size(4);
format %{ "LDF $src,$dst\t! stkI to regF" %} format %{ "LDF $src,$dst\t! stkI to regF" %}
opcode(Assembler::ldf_op3); opcode(Assembler::ldf_op3);
ins_encode(form3_mem_reg(src, dst)); ins_encode(simple_form3_mem_reg(src, dst));
ins_pipe(floadF_stk); ins_pipe(floadF_stk);
%} %}
@ -5073,7 +5086,7 @@ instruct stkL_to_regD(regD dst, stackSlotL src) %{
size(4); size(4);
format %{ "LDDF $src,$dst\t! stkL to regD" %} format %{ "LDDF $src,$dst\t! stkL to regD" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode(form3_mem_reg(src, dst)); ins_encode(simple_form3_mem_reg(src, dst));
ins_pipe(floadD_stk); ins_pipe(floadD_stk);
%} %}
@ -5084,7 +5097,7 @@ instruct regF_to_stkI(stackSlotI dst, regF src) %{
size(4); size(4);
format %{ "STF $src,$dst\t! regF to stkI" %} format %{ "STF $src,$dst\t! regF to stkI" %}
opcode(Assembler::stf_op3); opcode(Assembler::stf_op3);
ins_encode(form3_mem_reg(dst, src)); ins_encode(simple_form3_mem_reg(dst, src));
ins_pipe(fstoreF_stk_reg); ins_pipe(fstoreF_stk_reg);
%} %}
@ -5095,7 +5108,7 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{
size(4); size(4);
format %{ "STDF $src,$dst\t! regD to stkL" %} format %{ "STDF $src,$dst\t! regD to stkL" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode(form3_mem_reg(dst, src)); ins_encode(simple_form3_mem_reg(dst, src));
ins_pipe(fstoreD_stk_reg); 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" format %{ "STW $src,$dst.hi\t! long\n\t"
"STW R_G0,$dst.lo" %} "STW R_G0,$dst.lo" %}
opcode(Assembler::stw_op3); 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); ins_pipe(lstoreI_stk_reg);
%} %}
@ -5117,7 +5130,7 @@ instruct regL_to_stkD(stackSlotD dst, iRegL src) %{
size(4); size(4);
format %{ "STX $src,$dst\t! regL to stkD" %} format %{ "STX $src,$dst\t! regL to stkD" %}
opcode(Assembler::stx_op3); opcode(Assembler::stx_op3);
ins_encode( form3_mem_reg( dst, src ) ); ins_encode(simple_form3_mem_reg( dst, src ) );
ins_pipe(istore_stk_reg); ins_pipe(istore_stk_reg);
%} %}
@ -5131,7 +5144,7 @@ instruct stkI_to_regI( iRegI dst, stackSlotI src ) %{
size(4); size(4);
format %{ "LDUW $src,$dst\t!stk" %} format %{ "LDUW $src,$dst\t!stk" %}
opcode(Assembler::lduw_op3); opcode(Assembler::lduw_op3);
ins_encode( form3_mem_reg( src, dst ) ); ins_encode(simple_form3_mem_reg( src, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -5143,7 +5156,7 @@ instruct regI_to_stkI( stackSlotI dst, iRegI src ) %{
size(4); size(4);
format %{ "STW $src,$dst\t!stk" %} format %{ "STW $src,$dst\t!stk" %}
opcode(Assembler::stw_op3); opcode(Assembler::stw_op3);
ins_encode( form3_mem_reg( dst, src ) ); ins_encode(simple_form3_mem_reg( dst, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -5155,7 +5168,7 @@ instruct stkL_to_regL( iRegL dst, stackSlotL src ) %{
size(4); size(4);
format %{ "LDX $src,$dst\t! long" %} format %{ "LDX $src,$dst\t! long" %}
opcode(Assembler::ldx_op3); opcode(Assembler::ldx_op3);
ins_encode( form3_mem_reg( src, dst ) ); ins_encode(simple_form3_mem_reg( src, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -5167,7 +5180,7 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{
size(4); size(4);
format %{ "STX $src,$dst\t! long" %} format %{ "STX $src,$dst\t! long" %}
opcode(Assembler::stx_op3); opcode(Assembler::stx_op3);
ins_encode( form3_mem_reg( dst, src ) ); ins_encode(simple_form3_mem_reg( dst, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -5179,7 +5192,7 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{
size(4); size(4);
format %{ "LDX $src,$dst\t!ptr" %} format %{ "LDX $src,$dst\t!ptr" %}
opcode(Assembler::ldx_op3); opcode(Assembler::ldx_op3);
ins_encode( form3_mem_reg( src, dst ) ); ins_encode(simple_form3_mem_reg( src, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -5190,7 +5203,7 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{
size(4); size(4);
format %{ "STX $src,$dst\t!ptr" %} format %{ "STX $src,$dst\t!ptr" %}
opcode(Assembler::stx_op3); opcode(Assembler::stx_op3);
ins_encode( form3_mem_reg( dst, src ) ); ins_encode(simple_form3_mem_reg( dst, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
#else // _LP64 #else // _LP64
@ -5200,7 +5213,7 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
format %{ "LDUW $src,$dst\t!ptr" %} format %{ "LDUW $src,$dst\t!ptr" %}
opcode(Assembler::lduw_op3, Assembler::ldst_op); 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); ins_pipe(iload_mem);
%} %}
@ -5210,7 +5223,7 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
format %{ "STW $src,$dst\t!ptr" %} format %{ "STW $src,$dst\t!ptr" %}
opcode(Assembler::stw_op3, Assembler::ldst_op); 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); ins_pipe(istore_mem_reg);
%} %}
#endif // _LP64 #endif // _LP64
@ -5273,7 +5286,7 @@ instruct loadB(iRegI dst, memory mem) %{
size(4); size(4);
format %{ "LDSB $mem,$dst" %} format %{ "LDSB $mem,$dst" %}
opcode(Assembler::ldsb_op3); opcode(Assembler::ldsb_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mask_mem); ins_pipe(iload_mask_mem);
%} %}
@ -5285,7 +5298,7 @@ instruct loadUB(iRegI dst, memory mem, immI_255 bytemask) %{
size(4); size(4);
format %{ "LDUB $mem,$dst" %} format %{ "LDUB $mem,$dst" %}
opcode(Assembler::ldub_op3); opcode(Assembler::ldub_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mask_mem); ins_pipe(iload_mask_mem);
%} %}
@ -5297,7 +5310,7 @@ instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{
size(4); size(4);
format %{ "LDUB $mem,$dst" %} format %{ "LDUB $mem,$dst" %}
opcode(Assembler::ldub_op3); opcode(Assembler::ldub_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mask_mem); ins_pipe(iload_mask_mem);
%} %}
@ -5309,7 +5322,7 @@ instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{
size(4); size(4);
format %{ "LDUH $mem,$dst" %} format %{ "LDUH $mem,$dst" %}
opcode(Assembler::lduh_op3); opcode(Assembler::lduh_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mask_mem); ins_pipe(iload_mask_mem);
%} %}
@ -5321,7 +5334,7 @@ instruct loadC(iRegI dst, memory mem) %{
size(4); size(4);
format %{ "LDUH $mem,$dst" %} format %{ "LDUH $mem,$dst" %}
opcode(Assembler::lduh_op3); opcode(Assembler::lduh_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mask_mem); ins_pipe(iload_mask_mem);
%} %}
@ -5333,7 +5346,7 @@ instruct loadI(iRegI dst, memory mem) %{
format %{ "LDUW $mem,$dst" %} format %{ "LDUW $mem,$dst" %}
opcode(Assembler::lduw_op3); opcode(Assembler::lduw_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -5344,7 +5357,7 @@ instruct loadL(iRegL dst, memory mem ) %{
size(4); size(4);
format %{ "LDX $mem,$dst\t! long" %} format %{ "LDX $mem,$dst\t! long" %}
opcode(Assembler::ldx_op3); opcode(Assembler::ldx_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -5359,7 +5372,7 @@ instruct loadL_unaligned(iRegL dst, memory mem, o7RegI tmp) %{
"\tSLLX #32, $dst, $dst\n" "\tSLLX #32, $dst, $dst\n"
"\tOR $dst, R_O7, $dst" %} "\tOR $dst, R_O7, $dst" %}
opcode(Assembler::lduw_op3); 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); ins_pipe(iload_mem);
%} %}
@ -5370,7 +5383,7 @@ instruct loadA8B(regD dst, memory mem) %{
size(4); size(4);
format %{ "LDDF $mem,$dst\t! packed8B" %} format %{ "LDDF $mem,$dst\t! packed8B" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadD_mem); ins_pipe(floadD_mem);
%} %}
@ -5381,7 +5394,7 @@ instruct loadA4C(regD dst, memory mem) %{
size(4); size(4);
format %{ "LDDF $mem,$dst\t! packed4C" %} format %{ "LDDF $mem,$dst\t! packed4C" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadD_mem); ins_pipe(floadD_mem);
%} %}
@ -5392,7 +5405,7 @@ instruct loadA4S(regD dst, memory mem) %{
size(4); size(4);
format %{ "LDDF $mem,$dst\t! packed4S" %} format %{ "LDDF $mem,$dst\t! packed4S" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadD_mem); ins_pipe(floadD_mem);
%} %}
@ -5403,7 +5416,7 @@ instruct loadA2I(regD dst, memory mem) %{
size(4); size(4);
format %{ "LDDF $mem,$dst\t! packed2I" %} format %{ "LDDF $mem,$dst\t! packed2I" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadD_mem); ins_pipe(floadD_mem);
%} %}
@ -5415,7 +5428,7 @@ instruct loadRange(iRegI dst, memory mem) %{
size(4); size(4);
format %{ "LDUW $mem,$dst\t! range" %} format %{ "LDUW $mem,$dst\t! range" %}
opcode(Assembler::lduw_op3); opcode(Assembler::lduw_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -5427,7 +5440,7 @@ instruct loadI_freg(regF dst, memory mem) %{
format %{ "LDF $mem,$dst\t! for fitos/fitod" %} format %{ "LDF $mem,$dst\t! for fitos/fitod" %}
opcode(Assembler::ldf_op3); opcode(Assembler::ldf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadF_mem); ins_pipe(floadF_mem);
%} %}
@ -5514,7 +5527,7 @@ instruct loadS(iRegI dst, memory mem) %{
size(4); size(4);
format %{ "LDSH $mem,$dst" %} format %{ "LDSH $mem,$dst" %}
opcode(Assembler::ldsh_op3); opcode(Assembler::ldsh_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mask_mem); ins_pipe(iload_mask_mem);
%} %}
@ -5526,7 +5539,7 @@ instruct loadD(regD dst, memory mem) %{
size(4); size(4);
format %{ "LDDF $mem,$dst" %} format %{ "LDDF $mem,$dst" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadD_mem); ins_pipe(floadD_mem);
%} %}
@ -5550,7 +5563,7 @@ instruct loadF(regF dst, memory mem) %{
size(4); size(4);
format %{ "LDF $mem,$dst" %} format %{ "LDF $mem,$dst" %}
opcode(Assembler::ldf_op3); opcode(Assembler::ldf_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(floadF_mem); ins_pipe(floadF_mem);
%} %}
@ -5719,7 +5732,7 @@ instruct storeB(memory mem, iRegI src) %{
size(4); size(4);
format %{ "STB $src,$mem\t! byte" %} format %{ "STB $src,$mem\t! byte" %}
opcode(Assembler::stb_op3); opcode(Assembler::stb_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -5730,7 +5743,7 @@ instruct storeB0(memory mem, immI0 src) %{
size(4); size(4);
format %{ "STB $src,$mem\t! byte" %} format %{ "STB $src,$mem\t! byte" %}
opcode(Assembler::stb_op3); 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); ins_pipe(istore_mem_zero);
%} %}
@ -5741,7 +5754,7 @@ instruct storeCM0(memory mem, immI0 src) %{
size(4); size(4);
format %{ "STB $src,$mem\t! CMS card-mark byte 0" %} format %{ "STB $src,$mem\t! CMS card-mark byte 0" %}
opcode(Assembler::stb_op3); 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); ins_pipe(istore_mem_zero);
%} %}
@ -5753,7 +5766,7 @@ instruct storeC(memory mem, iRegI src) %{
size(4); size(4);
format %{ "STH $src,$mem\t! short" %} format %{ "STH $src,$mem\t! short" %}
opcode(Assembler::sth_op3); opcode(Assembler::sth_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -5764,7 +5777,7 @@ instruct storeC0(memory mem, immI0 src) %{
size(4); size(4);
format %{ "STH $src,$mem\t! short" %} format %{ "STH $src,$mem\t! short" %}
opcode(Assembler::sth_op3); 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); ins_pipe(istore_mem_zero);
%} %}
@ -5776,7 +5789,7 @@ instruct storeI(memory mem, iRegI src) %{
size(4); size(4);
format %{ "STW $src,$mem" %} format %{ "STW $src,$mem" %}
opcode(Assembler::stw_op3); opcode(Assembler::stw_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -5787,7 +5800,7 @@ instruct storeL(memory mem, iRegL src) %{
size(4); size(4);
format %{ "STX $src,$mem\t! long" %} format %{ "STX $src,$mem\t! long" %}
opcode(Assembler::stx_op3); opcode(Assembler::stx_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -5798,7 +5811,7 @@ instruct storeI0(memory mem, immI0 src) %{
size(4); size(4);
format %{ "STW $src,$mem" %} format %{ "STW $src,$mem" %}
opcode(Assembler::stw_op3); 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); ins_pipe(istore_mem_zero);
%} %}
@ -5809,7 +5822,7 @@ instruct storeL0(memory mem, immL0 src) %{
size(4); size(4);
format %{ "STX $src,$mem" %} format %{ "STX $src,$mem" %}
opcode(Assembler::stx_op3); 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); ins_pipe(istore_mem_zero);
%} %}
@ -5821,7 +5834,7 @@ instruct storeI_Freg(memory mem, regF src) %{
size(4); size(4);
format %{ "STF $src,$mem\t! after fstoi/fdtoi" %} format %{ "STF $src,$mem\t! after fstoi/fdtoi" %}
opcode(Assembler::stf_op3); opcode(Assembler::stf_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(fstoreF_mem_reg); ins_pipe(fstoreF_mem_reg);
%} %}
@ -5904,7 +5917,7 @@ instruct storeD( memory mem, regD src) %{
size(4); size(4);
format %{ "STDF $src,$mem" %} format %{ "STDF $src,$mem" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(fstoreD_mem_reg); ins_pipe(fstoreD_mem_reg);
%} %}
@ -5915,7 +5928,7 @@ instruct storeD0( memory mem, immD0 src) %{
size(4); size(4);
format %{ "STX $src,$mem" %} format %{ "STX $src,$mem" %}
opcode(Assembler::stx_op3); 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); ins_pipe(fstoreD_mem_zero);
%} %}
@ -5927,7 +5940,7 @@ instruct storeF( memory mem, regF src) %{
size(4); size(4);
format %{ "STF $src,$mem" %} format %{ "STF $src,$mem" %}
opcode(Assembler::stf_op3); opcode(Assembler::stf_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(fstoreF_mem_reg); ins_pipe(fstoreF_mem_reg);
%} %}
@ -5938,7 +5951,7 @@ instruct storeF0( memory mem, immF0 src) %{
size(4); size(4);
format %{ "STW $src,$mem\t! storeF0" %} format %{ "STW $src,$mem\t! storeF0" %}
opcode(Assembler::stw_op3); 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); ins_pipe(fstoreF_mem_zero);
%} %}
@ -5949,7 +5962,7 @@ instruct storeA8B(memory mem, regD src) %{
size(4); size(4);
format %{ "STDF $src,$mem\t! packed8B" %} format %{ "STDF $src,$mem\t! packed8B" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(fstoreD_mem_reg); ins_pipe(fstoreD_mem_reg);
%} %}
@ -6004,7 +6017,7 @@ instruct storeA8B0(memory mem, immI0 zero) %{
size(4); size(4);
format %{ "STX $zero,$mem\t! packed8B" %} format %{ "STX $zero,$mem\t! packed8B" %}
opcode(Assembler::stx_op3); 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); ins_pipe(fstoreD_mem_zero);
%} %}
@ -6015,7 +6028,7 @@ instruct storeA4C(memory mem, regD src) %{
size(4); size(4);
format %{ "STDF $src,$mem\t! packed4C" %} format %{ "STDF $src,$mem\t! packed4C" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(fstoreD_mem_reg); ins_pipe(fstoreD_mem_reg);
%} %}
@ -6026,7 +6039,7 @@ instruct storeA4C0(memory mem, immI0 zero) %{
size(4); size(4);
format %{ "STX $zero,$mem\t! packed4C" %} format %{ "STX $zero,$mem\t! packed4C" %}
opcode(Assembler::stx_op3); 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); ins_pipe(fstoreD_mem_zero);
%} %}
@ -6037,7 +6050,7 @@ instruct storeA2I(memory mem, regD src) %{
size(4); size(4);
format %{ "STDF $src,$mem\t! packed2I" %} format %{ "STDF $src,$mem\t! packed2I" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode( form3_mem_reg( mem, src ) ); ins_encode(simple_form3_mem_reg( mem, src ) );
ins_pipe(fstoreD_mem_reg); ins_pipe(fstoreD_mem_reg);
%} %}
@ -6048,7 +6061,7 @@ instruct storeA2I0(memory mem, immI0 zero) %{
size(4); size(4);
format %{ "STX $zero,$mem\t! packed2I" %} format %{ "STX $zero,$mem\t! packed2I" %}
opcode(Assembler::stx_op3); 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); ins_pipe(fstoreD_mem_zero);
%} %}
@ -6162,7 +6175,7 @@ instruct stfSSD(stackSlotD stkSlot, regD src) %{
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
format %{ "STDF $src,$stkSlot\t!stk" %} format %{ "STDF $src,$stkSlot\t!stk" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode(form3_mem_reg(stkSlot, src)); ins_encode(simple_form3_mem_reg(stkSlot, src));
ins_pipe(fstoreD_stk_reg); ins_pipe(fstoreD_stk_reg);
%} %}
@ -6172,7 +6185,7 @@ instruct ldfSSD(regD dst, stackSlotD stkSlot) %{
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
format %{ "LDDF $stkSlot,$dst\t!stk" %} format %{ "LDDF $stkSlot,$dst\t!stk" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode(form3_mem_reg(stkSlot, dst)); ins_encode(simple_form3_mem_reg(stkSlot, dst));
ins_pipe(floadD_stk); ins_pipe(floadD_stk);
%} %}
@ -6182,7 +6195,7 @@ instruct stfSSF(stackSlotF stkSlot, regF src) %{
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
format %{ "STF $src,$stkSlot\t!stk" %} format %{ "STF $src,$stkSlot\t!stk" %}
opcode(Assembler::stf_op3); opcode(Assembler::stf_op3);
ins_encode(form3_mem_reg(stkSlot, src)); ins_encode(simple_form3_mem_reg(stkSlot, src));
ins_pipe(fstoreF_stk_reg); ins_pipe(fstoreF_stk_reg);
%} %}
@ -6584,7 +6597,7 @@ instruct loadLLocked(iRegL dst, memory mem) %{
size(4); size(4);
format %{ "LDX $mem,$dst\t! long" %} format %{ "LDX $mem,$dst\t! long" %}
opcode(Assembler::ldx_op3); opcode(Assembler::ldx_op3);
ins_encode( form3_mem_reg( mem, dst ) ); ins_encode(simple_form3_mem_reg( mem, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -6597,32 +6610,23 @@ instruct storePConditional( iRegP heap_top_ptr, iRegP oldval, g3RegP newval, fla
ins_pipe( long_memory_op ); ins_pipe( long_memory_op );
%} %}
instruct storeLConditional_bool(iRegP mem_ptr, iRegL oldval, iRegL newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{ // Conditional-store of an int value.
match(Set res (StoreLConditional mem_ptr (Binary oldval newval))); instruct storeIConditional( iRegP mem_ptr, iRegI oldval, g3RegI newval, flagsReg icc ) %{
effect( USE mem_ptr, KILL ccr, KILL tmp1); match(Set icc (StoreIConditional mem_ptr (Binary oldval newval)));
// Marshal the register pairs into V9 64-bit registers, then do the compare-and-swap effect( KILL newval );
format %{ 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"
"MOV $newval,R_O7\n\t" "CMP $oldval,$newval\t\t! See if we made progress" %}
"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" ins_encode( enc_cas(mem_ptr,oldval,newval) );
"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) );
ins_pipe( long_memory_op ); ins_pipe( long_memory_op );
%} %}
instruct storeLConditional_flags(iRegP mem_ptr, iRegL oldval, iRegL newval, flagsRegL xcc, o7RegI tmp1, immI0 zero) %{ // Conditional-store of a long value.
match(Set xcc (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero)); instruct storeLConditional( iRegP mem_ptr, iRegL oldval, g3RegL newval, flagsRegL xcc ) %{
effect( USE mem_ptr, KILL tmp1); match(Set xcc (StoreLConditional mem_ptr (Binary oldval newval)));
// Marshal the register pairs into V9 64-bit registers, then do the compare-and-swap effect( KILL newval );
format %{ 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"
"MOV $newval,R_O7\n\t" "CMP $oldval,$newval\t\t! See if we made progress" %}
"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" ins_encode( enc_cas(mem_ptr,oldval,newval) );
"CMP $oldval,R_O7\t\t! See if we made progress"
%}
ins_encode( enc_casx(mem_ptr, oldval, newval));
ins_pipe( long_memory_op ); ins_pipe( long_memory_op );
%} %}
@ -7405,6 +7409,34 @@ instruct orL_reg_imm13(iRegL dst, iRegL src1, immL13 con) %{
ins_pipe(ialu_reg_imm); 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 // Xor Instructions
// Register Xor // Register Xor
instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 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" format %{ "LDF $mem,$dst\n\t"
"FITOD $dst,$dst" %} "FITOD $dst,$dst" %}
opcode(Assembler::ldf_op3, Assembler::fitod_opf); 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); ins_pipe(floadF_mem);
%} %}
@ -7696,7 +7728,7 @@ instruct convI2F_mem( regF dst, memory mem ) %{
format %{ "LDF $mem,$dst\n\t" format %{ "LDF $mem,$dst\n\t"
"FITOS $dst,$dst" %} "FITOS $dst,$dst" %}
opcode(Assembler::ldf_op3, Assembler::fitos_opf); 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); ins_pipe(floadF_mem);
%} %}
@ -7738,7 +7770,7 @@ instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{
size(4); size(4);
format %{ "LDUW $src,$dst\t! MoveF2I" %} format %{ "LDUW $src,$dst\t! MoveF2I" %}
opcode(Assembler::lduw_op3); opcode(Assembler::lduw_op3);
ins_encode( form3_mem_reg( src, dst ) ); ins_encode(simple_form3_mem_reg( src, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -7750,7 +7782,7 @@ instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{
size(4); size(4);
format %{ "LDF $src,$dst\t! MoveI2F" %} format %{ "LDF $src,$dst\t! MoveI2F" %}
opcode(Assembler::ldf_op3); opcode(Assembler::ldf_op3);
ins_encode(form3_mem_reg(src, dst)); ins_encode(simple_form3_mem_reg(src, dst));
ins_pipe(floadF_stk); ins_pipe(floadF_stk);
%} %}
@ -7762,7 +7794,7 @@ instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{
size(4); size(4);
format %{ "LDX $src,$dst\t! MoveD2L" %} format %{ "LDX $src,$dst\t! MoveD2L" %}
opcode(Assembler::ldx_op3); opcode(Assembler::ldx_op3);
ins_encode( form3_mem_reg( src, dst ) ); ins_encode(simple_form3_mem_reg( src, dst ) );
ins_pipe(iload_mem); ins_pipe(iload_mem);
%} %}
@ -7774,7 +7806,7 @@ instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{
size(4); size(4);
format %{ "LDDF $src,$dst\t! MoveL2D" %} format %{ "LDDF $src,$dst\t! MoveL2D" %}
opcode(Assembler::lddf_op3); opcode(Assembler::lddf_op3);
ins_encode(form3_mem_reg(src, dst)); ins_encode(simple_form3_mem_reg(src, dst));
ins_pipe(floadD_stk); ins_pipe(floadD_stk);
%} %}
@ -7786,7 +7818,7 @@ instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{
size(4); size(4);
format %{ "STF $src,$dst\t!MoveF2I" %} format %{ "STF $src,$dst\t!MoveF2I" %}
opcode(Assembler::stf_op3); opcode(Assembler::stf_op3);
ins_encode(form3_mem_reg(dst, src)); ins_encode(simple_form3_mem_reg(dst, src));
ins_pipe(fstoreF_stk_reg); ins_pipe(fstoreF_stk_reg);
%} %}
@ -7798,7 +7830,7 @@ instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{
size(4); size(4);
format %{ "STW $src,$dst\t!MoveI2F" %} format %{ "STW $src,$dst\t!MoveI2F" %}
opcode(Assembler::stw_op3); opcode(Assembler::stw_op3);
ins_encode( form3_mem_reg( dst, src ) ); ins_encode(simple_form3_mem_reg( dst, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}
@ -7810,7 +7842,7 @@ instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{
size(4); size(4);
format %{ "STDF $src,$dst\t!MoveD2L" %} format %{ "STDF $src,$dst\t!MoveD2L" %}
opcode(Assembler::stdf_op3); opcode(Assembler::stdf_op3);
ins_encode(form3_mem_reg(dst, src)); ins_encode(simple_form3_mem_reg(dst, src));
ins_pipe(fstoreD_stk_reg); ins_pipe(fstoreD_stk_reg);
%} %}
@ -7822,7 +7854,7 @@ instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{
size(4); size(4);
format %{ "STX $src,$dst\t!MoveL2D" %} format %{ "STX $src,$dst\t!MoveL2D" %}
opcode(Assembler::stx_op3); opcode(Assembler::stx_op3);
ins_encode( form3_mem_reg( dst, src ) ); ins_encode(simple_form3_mem_reg( dst, src ) );
ins_pipe(istore_mem_reg); ins_pipe(istore_mem_reg);
%} %}

View File

@ -956,7 +956,7 @@ class StubGenerator: public StubCodeGenerator {
// Load a little early; will load 1 off the end of the array. // 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. // Ok for now; revisit if we have other uses of this routine.
if (UseCompressedOops) { 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 { } else {
__ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
} }
@ -973,7 +973,7 @@ class StubGenerator: public StubCodeGenerator {
#ifdef _LP64 #ifdef _LP64
__ subcc(L2_super,L4_ooptmp,Rret); // Check for match; zero in Rret for a hit __ subcc(L2_super,L4_ooptmp,Rret); // Check for match; zero in Rret for a hit
__ br( Assembler::notEqual, false, Assembler::pt, loop ); __ 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 #else
ShouldNotReachHere(); ShouldNotReachHere();
#endif #endif

View File

@ -621,6 +621,10 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
debug_only(has_disp32 = true); debug_only(has_disp32 = true);
break; break;
case 0xF0: // Lock
assert(os::is_MP(), "only on MP");
goto again_after_prefix;
case 0xF3: // For SSE case 0xF3: // For SSE
case 0xF2: // For SSE2 case 0xF2: // For SSE2
switch (0xFF & *ip++) { switch (0xFF & *ip++) {

View File

@ -1780,7 +1780,8 @@ class MacroAssembler: public Assembler {
// check info (currently consumed only by C1). If // check info (currently consumed only by C1). If
// swap_reg_contains_mark is true then returns -1 as it is assumed // swap_reg_contains_mark is true then returns -1 as it is assumed
// the calling code has already passed any potential faults. // 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, bool swap_reg_contains_mark,
Label& done, Label* slow_case = NULL, Label& done, Label* slow_case = NULL,
BiasedLockingCounters* counters = NULL); BiasedLockingCounters* counters = NULL);

View File

@ -495,8 +495,8 @@ void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
Compile* C = ra_->C; Compile* C = ra_->C;
if( C->in_24_bit_fp_mode() ) { if( C->in_24_bit_fp_mode() ) {
tty->print("FLDCW 24 bit fpu control word"); st->print("FLDCW 24 bit fpu control word");
tty->print_cr(""); tty->print("\t"); st->print_cr(""); st->print("\t");
} }
int framesize = C->frame_slots() << LogBytesPerInt; 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. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(framesize)) { 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 if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth
tty->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check");
tty->print_cr(""); tty->print("\t"); st->print_cr(""); st->print("\t");
framesize -= wordSize; framesize -= wordSize;
} }
if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) {
if (framesize) { if (framesize) {
tty->print("SUB ESP,%d\t# Create frame",framesize); st->print("SUB ESP,%d\t# Create frame",framesize);
} }
} else { } else {
tty->print("SUB ESP,%d\t# Create frame",framesize); st->print("SUB ESP,%d\t# Create frame",framesize);
} }
} }
#endif #endif
@ -725,18 +725,19 @@ static enum RC rc_class( OptoReg::Name reg ) {
return rc_xmm; 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 ) { if( cbuf ) {
emit_opcode (*cbuf, opcode ); emit_opcode (*cbuf, opcode );
encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false); encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false);
#ifndef PRODUCT #ifndef PRODUCT
} else if( !do_size ) { } 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( opcode == 0x8B || opcode == 0x89 ) { // MOV
if( is_load ) tty->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset);
else tty->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]);
} else { // FLD, FST, PUSH, POP } else { // FLD, FST, PUSH, POP
tty->print("%s [ESP + #%d]",op_str,offset); st->print("%s [ESP + #%d]",op_str,offset);
} }
#endif #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. // Helper for XMM registers. Extra opcode bits, limited syntax.
static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, 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( cbuf ) {
if( reg_lo+1 == reg_hi ) { // double move? if( reg_lo+1 == reg_hi ) { // double move?
if( is_load && !UseXmmLoadAndClearUpper ) 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); encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false);
#ifndef PRODUCT #ifndef PRODUCT
} else if( !do_size ) { } 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( 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", UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD",
Matcher::regName[reg_lo], offset); Matcher::regName[reg_lo], offset);
else tty->print("MOVSD [ESP + #%d],%s", else st->print("MOVSD [ESP + #%d],%s",
offset, Matcher::regName[reg_lo]); offset, Matcher::regName[reg_lo]);
} else { } else {
if( is_load ) tty->print("MOVSS %s,[ESP + #%d]", if( is_load ) st->print("MOVSS %s,[ESP + #%d]",
Matcher::regName[reg_lo], offset); Matcher::regName[reg_lo], offset);
else tty->print("MOVSS [ESP + #%d],%s", else st->print("MOVSS [ESP + #%d],%s",
offset, Matcher::regName[reg_lo]); offset, Matcher::regName[reg_lo]);
} }
#endif #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, 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( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers
if( cbuf ) { if( cbuf ) {
if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { 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] ); emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] );
#ifndef PRODUCT #ifndef PRODUCT
} else if( !do_size ) { } 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? 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 { } 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 #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] ); emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] );
#ifndef PRODUCT #ifndef PRODUCT
} else if( !do_size ) { } 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? 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 { } 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 #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 ) { if( cbuf ) {
emit_opcode(*cbuf, 0x8B ); emit_opcode(*cbuf, 0x8B );
emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] ); emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] );
#ifndef PRODUCT #ifndef PRODUCT
} else if( !do_size ) { } else if( !do_size ) {
if( size != 0 ) tty->print("\n\t"); if( size != 0 ) st->print("\n\t");
tty->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]);
#endif #endif
} }
return size+2; 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( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there
if( cbuf ) { if( cbuf ) {
emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it) emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it)
emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] ); emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] );
#ifndef PRODUCT #ifndef PRODUCT
} else if( !do_size ) { } else if( !do_size ) {
if( size != 0 ) tty->print("\n\t"); if( size != 0 ) st->print("\n\t");
tty->print("FLD %s",Matcher::regName[src_lo]); st->print("FLD %s",Matcher::regName[src_lo]);
#endif #endif
} }
size += 2; 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" ); 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 { 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_first_rc == rc_stack && dst_first_rc == rc_stack ) {
if( src_second == dst_first ) { // overlapping stack copy ranges 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" ); 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,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); 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 src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits
} }
// move low 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,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); 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 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,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); size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st);
} }
return size; return size;
} }
@ -909,15 +911,15 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
// -------------------------------------- // --------------------------------------
// Check for integer reg-reg copy // Check for integer reg-reg copy
if( src_first_rc == rc_int && dst_first_rc == rc_int ) 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 // Check for integer store
if( src_first_rc == rc_int && dst_first_rc == rc_stack ) 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 // Check for integer load
if( dst_first_rc == rc_int && src_first_rc == rc_stack ) 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 // Check for float reg-reg copy
@ -951,7 +953,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
// Check for float store // Check for float store
if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { 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 // 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) || assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) ||
(src_first+1 == src_second && dst_first+1 == dst_second), (src_first+1 == src_second && dst_first+1 == dst_second),
"no non-adjacent float-moves" ); "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 // Check for xmm store
if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { 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 // Check for float xmm load
if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) { 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 // Copy from float reg to xmm reg
@ -1017,10 +1019,10 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
} }
size += 4; 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. // 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 ) { if( cbuf ) {
emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8] 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 // Check for second word int-int move
if( src_second_rc == rc_int && dst_second_rc == rc_int ) 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 // Check for second word integer store
if( src_second_rc == rc_int && dst_second_rc == rc_stack ) 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 // Check for second word integer load
if( dst_second_rc == rc_int && src_second_rc == rc_stack ) 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(); Unimplemented();
@ -1318,7 +1320,11 @@ const uint Matcher::vector_ideal_reg(void) {
// //
// NOTE: If the platform does not provide any short branch variants, then // NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0. // 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); return (-128 <= offset && offset <= 127);
} }
@ -3307,7 +3313,7 @@ encode %{
// Beware -- there's a subtle invariant that fetch of the markword // Beware -- there's a subtle invariant that fetch of the markword
// at [FETCH], below, will never observe a biased encoding (*101b). // at [FETCH], below, will never observe a biased encoding (*101b).
// If this invariant is not held we risk exclusion (safety) failure. // 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); 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 // Critically, the biased locking test must have precedence over
// and appear before the (box->dhw == 0) recursive stack-lock test. // and appear before the (box->dhw == 0) recursive stack-lock test.
if (UseBiasedLocking) { if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
} }
@ -5272,6 +5278,15 @@ operand eFlagsRegU() %{
interface(REG_INTER); 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 // Condition Code Register used by long compare
operand flagsReg_long_LTGE() %{ operand flagsReg_long_LTGE() %{
constraint(ALLOC_IN_RC(int_flags)); constraint(ALLOC_IN_RC(int_flags));
@ -5749,12 +5764,12 @@ operand cmpOp() %{
format %{ "" %} format %{ "" %}
interface(COND_INTER) %{ interface(COND_INTER) %{
equal(0x4); equal(0x4, "e");
not_equal(0x5); not_equal(0x5, "ne");
less(0xC); less(0xC, "l");
greater_equal(0xD); greater_equal(0xD, "ge");
less_equal(0xE); less_equal(0xE, "le");
greater(0xF); greater(0xF, "g");
%} %}
%} %}
@ -5766,12 +5781,47 @@ operand cmpOpU() %{
format %{ "" %} format %{ "" %}
interface(COND_INTER) %{ interface(COND_INTER) %{
equal(0x4); equal(0x4, "e");
not_equal(0x5); not_equal(0x5, "ne");
less(0x2); less(0x2, "b");
greater_equal(0x3); greater_equal(0x3, "nb");
less_equal(0x6); less_equal(0x6, "be");
greater(0x7); 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 %{ "" %} format %{ "" %}
interface(COND_INTER) %{ interface(COND_INTER) %{
equal(0x4); equal(0x4, "e");
not_equal(0x5); not_equal(0x5, "ne");
less(0xF); less(0xF, "g");
greater_equal(0xE); greater_equal(0xE, "le");
less_equal(0xD); less_equal(0xD, "ge");
greater(0xC); greater(0xC, "l");
%} %}
%} %}
@ -7357,7 +7407,7 @@ instruct cmovI_reg(eRegI dst, eRegI src, eFlagsReg cr, cmpOp cop ) %{
ins_pipe( pipe_cmov_reg ); 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() ); predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200); ins_cost(200);
@ -7367,6 +7417,15 @@ instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{
ins_pipe( pipe_cmov_reg ); 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 // Conditional move
instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{
predicate(VM_Version::supports_cmov() ); predicate(VM_Version::supports_cmov() );
@ -7379,7 +7438,7 @@ instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{
%} %}
// Conditional move // 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() ); predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250); ins_cost(250);
@ -7389,6 +7448,15 @@ instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{
ins_pipe( pipe_cmov_mem ); 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 // Conditional move
instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{
predicate(VM_Version::supports_cmov() ); predicate(VM_Version::supports_cmov() );
@ -7416,7 +7484,7 @@ instruct cmovP_reg_nonP6(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{
%} %}
// Conditional move // 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() ); predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200); ins_cost(200);
@ -7426,6 +7494,15 @@ instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{
ins_pipe( pipe_cmov_reg ); 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 // DISABLED: Requires the ADLC to emit a bottom_type call that
// correctly meets the two pointer arguments; one is an incoming // correctly meets the two pointer arguments; one is an incoming
// register but the other is a memory operand. ALSO appears to // 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 ); 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 // unsigned version
instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{
predicate (UseSSE>=2); predicate (UseSSE>=2);
@ -7573,6 +7659,15 @@ instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{
ins_pipe( pipe_slow ); 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) %{ instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{
predicate(VM_Version::supports_cmov() ); predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); 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 ); 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-------------------------------------------- //----------Arithmetic Instructions--------------------------------------------
//----------Addition Instructions---------------------------------------------- //----------Addition Instructions----------------------------------------------
// Integer Addition Instructions // Integer Addition Instructions
@ -7826,33 +7930,36 @@ instruct storePConditional( memory heap_top_ptr, eAXRegP oldval, eRegP newval, e
ins_pipe( pipe_cmpxchg ); ins_pipe( pipe_cmpxchg );
%} %}
// Conditional-store of a long value // Conditional-store of an int value.
// Returns a boolean value (0/1) on success. Implemented with a CMPXCHG8 on Intel. // ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG on Intel.
// mem_ptr can actually be in either ESI or EDI instruct storeIConditional( memory mem, eAXRegI oldval, eRegI newval, eFlagsReg cr ) %{
instruct storeLConditional( eRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{ match(Set cr (StoreIConditional mem (Binary oldval newval)));
match(Set res (StoreLConditional mem_ptr (Binary oldval newval))); effect(KILL oldval);
effect(KILL cr); format %{ "CMPXCHG $mem,$newval\t# If EAX==$mem Then store $newval into $mem" %}
// EDX:EAX is killed if there is contention, but then it's also unused. ins_encode( lock_prefix, Opcode(0x0F), Opcode(0xB1), RegMem(newval, mem) );
// 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) );
ins_pipe( pipe_cmpxchg ); ins_pipe( pipe_cmpxchg );
%} %}
// Conditional-store of a long value // Conditional-store of a long value.
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG8 on Intel. // 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( memory mem, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
instruct storeLConditional_flags( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr, immI0 zero ) %{ match(Set cr (StoreLConditional mem (Binary oldval newval)));
match(Set cr (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero)); effect(KILL oldval);
// EDX:EAX is killed if there is contention, but then it's also unused. format %{ "XCHG EBX,ECX\t# correct order for CMPXCHG8 instruction\n\t"
// In the common case of no contention, EDX:EAX holds the new oop address. "CMPXCHG8 $mem,ECX:EBX\t# If EDX:EAX==$mem Then store ECX:EBX into $mem\n\t"
format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %} "XCHG EBX,ECX"
ins_encode( enc_cmpxchg8(mem_ptr) ); %}
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 ); ins_pipe( pipe_cmpxchg );
%} %}
@ -8319,6 +8426,7 @@ instruct shrI_eReg_imm(eRegI dst, immI8 shift, eFlagsReg cr) %{
ins_pipe( ialu_reg ); ins_pipe( ialu_reg );
%} %}
// Logical Shift Right by 24, followed by Arithmetic Shift Left by 24. // Logical Shift Right by 24, followed by Arithmetic Shift Left by 24.
// This idiom is used by the compiler for the i2b bytecode. // This idiom is used by the compiler for the i2b bytecode.
instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour, eFlagsReg cr) %{ 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 ); 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 // Or Register with Immediate
instruct orI_eReg_imm(eRegI dst, immI src, eFlagsReg cr) %{ instruct orI_eReg_imm(eRegI dst, immI src, eFlagsReg cr) %{
match(Set dst (OrI dst src)); 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 ); 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 // Compare & branch
instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{
predicate(UseSSE<=1); predicate(UseSSE<=1);
@ -9264,6 +9396,16 @@ instruct cmpXD_cc(eFlagsRegU cr, regXD dst, regXD src, eAXRegI rax) %{
ins_pipe( pipe_slow ); 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 // float compare and set condition codes in EFLAGS by XMM regs
instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{
predicate(UseSSE>=2); predicate(UseSSE>=2);
@ -9280,6 +9422,16 @@ instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{
ins_pipe( pipe_slow ); 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 // Compare into -1,0,1 in XMM
instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{
predicate(UseSSE>=2); predicate(UseSSE>=2);
@ -10167,6 +10319,18 @@ instruct cmpF_cc_P6(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{
ins_pipe( pipe_slow ); 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 // Compare & branch
instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ 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 ); 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 // float compare and set condition codes in EFLAGS by XMM regs
instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{
predicate(UseSSE>=1); predicate(UseSSE>=1);
@ -10248,6 +10422,16 @@ instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{
ins_pipe( pipe_slow ); 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 // Compare into -1,0,1 in XMM
instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{
predicate(UseSSE>=1); predicate(UseSSE>=1);
@ -12099,6 +12283,19 @@ instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_pc_relative(1); 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 // Jump Direct Conditional - using unsigned comparison
instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
match(If cop cmp); match(If cop cmp);
@ -12108,8 +12305,63 @@ instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
format %{ "J$cop,u $labl" %} format %{ "J$cop,u $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); opcode(0x0F, 0x80);
ins_encode( Jcc( cop, labl) ); ins_encode(Jcc(cop, labl));
ins_pipe( pipe_jcc ); 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); ins_pc_relative(1);
%} %}
@ -12208,7 +12460,7 @@ instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{
effect(USE labl); effect(USE labl);
ins_cost(300); ins_cost(300);
format %{ "J$cop,s $labl" %} format %{ "J$cop,s $labl\t# Loop end" %}
size(2); size(2);
opcode(0x70); opcode(0x70);
ins_encode( JccShort( cop, labl) ); ins_encode( JccShort( cop, labl) );
@ -12223,7 +12475,21 @@ instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
effect(USE labl); effect(USE labl);
ins_cost(300); 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); size(2);
opcode(0x70); opcode(0x70);
ins_encode( JccShort( cop, labl) ); ins_encode( JccShort( cop, labl) );
@ -12247,6 +12513,60 @@ instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_short_branch(1); 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 // Long Compare
// //

View File

@ -2004,9 +2004,12 @@ const uint Matcher::vector_ideal_reg(void) {
// //
// NOTE: If the platform does not provide any short branch variants, then // NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0. // 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,
return -0x80 <= offset && offset < 0x80; // 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) { const bool Matcher::isSimpleConstant64(jlong value) {
@ -3569,7 +3572,7 @@ encode %{
// at [FETCH], below, will never observe a biased encoding (*101b). // at [FETCH], below, will never observe a biased encoding (*101b).
// If this invariant is not held we'll suffer exclusion (safety) failure. // 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.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters);
masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH] masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH]
} }
@ -3657,7 +3660,7 @@ encode %{
} else { } else {
Label DONE_LABEL, Stacked, CheckSucc ; Label DONE_LABEL, Stacked, CheckSucc ;
if (UseBiasedLocking) { if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
} }
@ -5134,6 +5137,15 @@ operand rFlagsRegU()
interface(REG_INTER); 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 // Float register operands
operand regF() operand regF()
%{ %{
@ -5405,12 +5417,12 @@ operand cmpOp()
format %{ "" %} format %{ "" %}
interface(COND_INTER) %{ interface(COND_INTER) %{
equal(0x4); equal(0x4, "e");
not_equal(0x5); not_equal(0x5, "ne");
less(0xC); less(0xC, "l");
greater_equal(0xD); greater_equal(0xD, "ge");
less_equal(0xE); less_equal(0xE, "le");
greater(0xF); greater(0xF, "g");
%} %}
%} %}
@ -5423,12 +5435,48 @@ operand cmpOpU()
format %{ "" %} format %{ "" %}
interface(COND_INTER) %{ interface(COND_INTER) %{
equal(0x4); equal(0x4, "e");
not_equal(0x5); not_equal(0x5, "ne");
less(0x2); less(0x2, "b");
greater_equal(0x3); greater_equal(0x3, "nb");
less_equal(0x6); less_equal(0x6, "be");
greater(0x7); 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); 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))); match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX ins_cost(200); // XXX
@ -7187,9 +7234,16 @@ instruct cmovI_regU(rRegI dst, rRegI src, rFlagsRegU cr, cmpOpU cop)
ins_pipe(pipe_cmov_reg); 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 // 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)))); match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250); // XXX ins_cost(250); // XXX
@ -7211,6 +7265,14 @@ instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
ins_pipe(pipe_cmov_mem); 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 // Conditional move
instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop) 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 // 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))); 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); 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 // Conditional move
instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) 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 // 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))); 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 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 // DISABLED: Requires the ADLC to emit a bottom_type call that
// correctly meets the two pointer arguments; one is an incoming // correctly meets the two pointer arguments; one is an incoming
// register but the other is a memory operand. ALSO appears to // 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 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) instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
%{ %{
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL 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 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) instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src)
%{ %{
match(Set dst (CMoveF (Binary cop cr) (Binary dst 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); 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) instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src)
%{ %{
match(Set dst (CMoveD (Binary cop cr) (Binary dst 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); 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-------------------------------------------- //----------Arithmetic Instructions--------------------------------------------
//----------Addition Instructions---------------------------------------------- //----------Addition Instructions----------------------------------------------
@ -7735,7 +7845,7 @@ instruct storePConditional(memory heap_top_ptr,
rFlagsReg cr) rFlagsReg cr)
%{ %{
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval))); match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) " format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
"If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %} "If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
opcode(0x0F, 0xB1); opcode(0x0F, 0xB1);
@ -7746,53 +7856,40 @@ instruct storePConditional(memory heap_top_ptr,
ins_pipe(pipe_cmpxchg); ins_pipe(pipe_cmpxchg);
%} %}
// Conditional-store of a long value // Conditional-store of an int value.
// Returns a boolean value (0/1) on success. Implemented with a // ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG.
// CMPXCHG8 on Intel. mem_ptr can actually be in either RSI or RDI instruct storeIConditional(memory mem, rax_RegI oldval, rRegI newval, rFlagsReg cr)
instruct storeLConditional(rRegI res,
memory mem_ptr,
rax_RegL oldval, rRegL newval,
rFlagsReg cr)
%{ %{
match(Set res (StoreLConditional mem_ptr (Binary oldval newval))); match(Set cr (StoreIConditional mem (Binary oldval newval)));
effect(KILL cr); effect(KILL oldval);
format %{ "cmpxchgq $mem_ptr, $newval\t# (long) " format %{ "cmpxchgl $mem, $newval\t# If rax == $mem then store $newval into $mem" %}
"If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
"sete $res\n\t"
"movzbl $res, $res" %}
opcode(0x0F, 0xB1); opcode(0x0F, 0xB1);
ins_encode(lock_prefix, ins_encode(lock_prefix,
REX_reg_mem_wide(newval, mem_ptr), REX_reg_mem(newval, mem),
OpcP, OpcS, OpcP, OpcS,
reg_mem(newval, mem_ptr), reg_mem(newval, mem));
REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete
REX_reg_breg(res, res), // movzbl
Opcode(0xF), Opcode(0xB6), reg_reg(res, res));
ins_pipe(pipe_cmpxchg); ins_pipe(pipe_cmpxchg);
%} %}
// Conditional-store of a long value // Conditional-store of a long value.
// ZF flag is set on success, reset otherwise. Implemented with a // ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG.
// CMPXCHG8 on Intel. mem_ptr can actually be in either RSI or RDI instruct storeLConditional(memory mem, rax_RegL oldval, rRegL newval, rFlagsReg cr)
instruct storeLConditional_flags(memory mem_ptr,
rax_RegL oldval, rRegL newval,
rFlagsReg cr,
immI0 zero)
%{ %{
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) " format %{ "cmpxchgq $mem, $newval\t# If rax == $mem then store $newval into $mem" %}
"If rax == $mem_ptr then store $newval into $mem_ptr" %}
opcode(0x0F, 0xB1); opcode(0x0F, 0xB1);
ins_encode(lock_prefix, ins_encode(lock_prefix,
REX_reg_mem_wide(newval, mem_ptr), REX_reg_mem_wide(newval, mem),
OpcP, OpcS, OpcP, OpcS,
reg_mem(newval, mem_ptr)); reg_mem(newval, mem));
ins_pipe(pipe_cmpxchg); ins_pipe(pipe_cmpxchg);
%} %}
// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
instruct compareAndSwapP(rRegI res, instruct compareAndSwapP(rRegI res,
memory mem_ptr, memory mem_ptr,
rax_RegP oldval, rRegP newval, rax_RegP oldval, rRegP newval,
@ -7816,7 +7913,6 @@ instruct compareAndSwapP(rRegI res,
ins_pipe( pipe_cmpxchg ); ins_pipe( pipe_cmpxchg );
%} %}
// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
instruct compareAndSwapL(rRegI res, instruct compareAndSwapL(rRegI res,
memory mem_ptr, memory mem_ptr,
rax_RegL oldval, rRegL newval, rax_RegL oldval, rRegL newval,
@ -8766,6 +8862,7 @@ instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_reg); ins_pipe(ialu_reg);
%} %}
// Logical Shift Right by 8-bit immediate // Logical Shift Right by 8-bit immediate
instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr) 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); 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 // Or Register with Immediate
instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr) 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); 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) instruct cmpF_cc_mem(rFlagsRegU cr, regF src1, memory src2)
%{ %{
match(Set cr (CmpF src1 (LoadF 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); 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) instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2)
%{ %{
match(Set cr (CmpF src1 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); 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) instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
%{ %{
match(Set cr (CmpD src1 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); 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) instruct cmpD_cc_mem(rFlagsRegU cr, regD src1, memory src2)
%{ %{
match(Set cr (CmpD src1 (LoadD 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); 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) instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2)
%{ %{
match(Set cr (CmpD src1 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); 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 // Compare into -1,0,1
instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr) 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 // 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); match(CountedLoopEnd cop cmp);
effect(USE labl); effect(USE labl);
@ -11420,14 +11590,26 @@ instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_pc_relative(1); 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 // 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); match(If cop cmp);
effect(USE labl); effect(USE labl);
ins_cost(300); ins_cost(300);
format %{ "j$cop,u $labl" %} format %{ "j$cop,u $labl" %}
size(6); size(6);
opcode(0x0F, 0x80); opcode(0x0F, 0x80);
ins_encode(Jcc(cop, labl)); ins_encode(Jcc(cop, labl));
@ -11435,6 +11617,59 @@ instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_pc_relative(1); 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 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary
// superklass array for an instance of the superklass. Set a hidden // 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. // specific code section of the file.
// Jump Direct - Label defines a relative address from JMP+1 // Jump Direct - Label defines a relative address from JMP+1
instruct jmpDir_short(label labl) instruct jmpDir_short(label labl) %{
%{
match(Goto); match(Goto);
effect(USE labl); effect(USE labl);
@ -11521,8 +11755,7 @@ instruct jmpDir_short(label labl)
%} %}
// Jump Direct Conditional - Label defines a relative address from Jcc+1 // 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); match(If cop cr);
effect(USE labl); 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 // 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); match(CountedLoopEnd cop cr);
effect(USE labl); effect(USE labl);
ins_cost(300); ins_cost(300);
format %{ "j$cop,s $labl" %} format %{ "j$cop,s $labl\t# loop end" %}
size(2); size(2);
opcode(0x70); opcode(0x70);
ins_encode(JccShort(cop, labl)); 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 // 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); match(CountedLoopEnd cop cmp);
effect(USE labl); 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); ins_cost(300);
format %{ "j$cop,us $labl" %} format %{ "j$cop,us $labl" %}
size(2); size(2);
@ -11568,9 +11828,7 @@ instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_short_branch(1); ins_short_branch(1);
%} %}
// Jump Direct Conditional - using unsigned comparison instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
%{
match(If cop cmp); match(If cop cmp);
effect(USE labl); effect(USE labl);
@ -11584,6 +11842,46 @@ instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_short_branch(1); 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 // inlined locking and unlocking

View File

@ -103,16 +103,16 @@ encode %{
// This name is KNOWN by the ADLC and cannot be changed. // This name is KNOWN by the ADLC and cannot be changed.
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
// for this guy. // for this guy.
instruct tlsLoadP(eAXRegP dst, eFlagsReg cr) %{ instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
match(Set dst (ThreadLocal)); match(Set dst (ThreadLocal));
effect(DEF dst, KILL cr); effect(DEF dst, KILL cr);
format %{ "MOV EAX, Thread::current()" %} format %{ "MOV $dst, Thread::current()" %}
ins_encode( linux_tlsencode(dst) ); ins_encode( linux_tlsencode(dst) );
ins_pipe( ialu_reg_fat ); ins_pipe( ialu_reg_fat );
%} %}
instruct TLS(eAXRegP dst) %{ instruct TLS(eRegP dst) %{
match(Set dst (ThreadLocal)); match(Set dst (ThreadLocal));
expand %{ expand %{

View File

@ -110,16 +110,16 @@ encode %{
// This name is KNOWN by the ADLC and cannot be changed. // This name is KNOWN by the ADLC and cannot be changed.
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
// for this guy. // for this guy.
instruct tlsLoadP(eAXRegP dst, eFlagsReg cr) %{ instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
match(Set dst (ThreadLocal)); match(Set dst (ThreadLocal));
effect(DEF dst, KILL cr); effect(DEF dst, KILL cr);
format %{ "MOV EAX, Thread::current()" %} format %{ "MOV $dst, Thread::current()" %}
ins_encode( solaris_tlsencode(dst) ); ins_encode( solaris_tlsencode(dst) );
ins_pipe( ialu_reg_fat ); ins_pipe( ialu_reg_fat );
%} %}
instruct TLS(eAXRegP dst) %{ instruct TLS(eRegP dst) %{
match(Set dst (ThreadLocal)); match(Set dst (ThreadLocal));
expand %{ expand %{

View File

@ -28,6 +28,7 @@ import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider; import com.sun.hotspot.igv.data.services.InputGraphProvider;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.io.Serializable; import java.io.Serializable;
import javax.swing.SwingUtilities;
import org.openide.ErrorManager; import org.openide.ErrorManager;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils; import org.openide.explorer.ExplorerUtils;
@ -151,14 +152,18 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
} }
public void resultChanged(LookupEvent lookupEvent) { public void resultChanged(LookupEvent lookupEvent) {
InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class); final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
if (p != null) { if (p != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InputGraph graph = p.getGraph(); InputGraph graph = p.getGraph();
if (graph != null) { if (graph != null) {
Group g = graph.getGroup(); Group g = graph.getGroup();
rootNode.update(graph, g.getMethod()); rootNode.update(graph, g.getMethod());
} }
} }
});
}
} }
final static class ResolvableHelper implements Serializable { final static class ResolvableHelper implements Serializable {

View File

@ -33,7 +33,7 @@ import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.HashMap;
import java.util.Set; import java.util.Set;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import org.netbeans.api.visual.action.ActionFactory; 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.action.WidgetAction;
import org.netbeans.api.visual.anchor.AnchorFactory; import org.netbeans.api.visual.anchor.AnchorFactory;
import org.netbeans.api.visual.anchor.AnchorShape; 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.layout.LayoutFactory;
import org.netbeans.api.visual.router.RouterFactory; import org.netbeans.api.visual.router.RouterFactory;
import org.netbeans.api.visual.widget.LayerWidget; import org.netbeans.api.visual.widget.LayerWidget;
@ -61,8 +60,8 @@ import org.openide.util.Lookup;
*/ */
public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider { public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
private Set<BlockWidget> selection; private HashSet<BlockWidget> selection;
private Hashtable<InputBlock, BlockWidget> blockMap; private HashMap<InputBlock, BlockWidget> blockMap;
private InputGraph oldGraph; private InputGraph oldGraph;
private LayerWidget edgeLayer; private LayerWidget edgeLayer;
private LayerWidget mainLayer; private LayerWidget mainLayer;

View File

@ -28,6 +28,7 @@ import com.sun.hotspot.igv.data.services.InputGraphProvider;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.io.Serializable; import java.io.Serializable;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import org.openide.ErrorManager; import org.openide.ErrorManager;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.LookupEvent; import org.openide.util.LookupEvent;
@ -143,13 +144,17 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
public void resultChanged(LookupEvent lookupEvent) { public void resultChanged(LookupEvent lookupEvent) {
InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class); final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
if (p != null) { if (p != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InputGraph g = p.getGraph(); InputGraph g = p.getGraph();
if (g != null) { if (g != null) {
scene.setGraph(g); scene.setGraph(g);
} }
} }
});
}
} }
@Override @Override

View File

@ -24,6 +24,7 @@
package com.sun.hotspot.igv.coordinator; package com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.coordinator.actions.RemoveCookie; 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.Group;
import com.sun.hotspot.igv.data.services.GroupOrganizer; import com.sun.hotspot.igv.data.services.GroupOrganizer;
import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.InputGraph;
@ -50,17 +51,24 @@ public class FolderNode extends AbstractNode {
private List<String> subFolders; private List<String> subFolders;
private FolderChildren children; private FolderChildren children;
private static class FolderChildren extends Children.Keys { private static class FolderChildren extends Children.Keys implements ChangedListener<Group> {
private FolderNode parent; private FolderNode parent;
private List<Group> registeredGroups;
public void setParent(FolderNode parent) { public void setParent(FolderNode parent) {
this.parent = parent; this.parent = parent;
this.registeredGroups = new ArrayList<Group>();
} }
@Override @Override
protected Node[] createNodes(Object arg0) { protected Node[] createNodes(Object arg0) {
for(Group g : registeredGroups) {
g.getChangedEvent().removeListener(this);
}
registeredGroups.clear();
Pair<String, List<Group>> p = (Pair<String, List<Group>>) arg0; Pair<String, List<Group>> p = (Pair<String, List<Group>>) arg0;
if (p.getLeft().length() == 0) { if (p.getLeft().length() == 0) {
@ -69,6 +77,8 @@ public class FolderNode extends AbstractNode {
for (InputGraph graph : g.getGraphs()) { for (InputGraph graph : g.getGraphs()) {
curNodes.add(new GraphNode(graph)); curNodes.add(new GraphNode(graph));
} }
g.getChangedEvent().addListener(this);
registeredGroups.add(g);
} }
Node[] result = new Node[curNodes.size()]; Node[] result = new Node[curNodes.size()];
@ -85,7 +95,13 @@ public class FolderNode extends AbstractNode {
@Override @Override
public void addNotify() { public void addNotify() {
this.setKeys(parent.structure); this.setKeys(parent.structure);
}
public void changed(Group source) {
List<Pair<String, List<Group>>> newStructure = new ArrayList<Pair<String, List<Group>>>();
for(Pair<String, List<Group>> p : parent.structure) {
refreshKey(p);
}
} }
} }

View File

@ -31,7 +31,7 @@ import java.util.List;
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class GraphDocument extends Properties.Object implements ChangedEventProvider<GraphDocument> { public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument> {
private List<Group> groups; private List<Group> groups;
private ChangedEvent<GraphDocument> changedEvent; private ChangedEvent<GraphDocument> changedEvent;

View File

@ -37,7 +37,7 @@ import java.util.Set;
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class Group extends Properties.Object implements ChangedEventProvider<Group> { public class Group extends Properties.Entity implements ChangedEventProvider<Group> {
private List<InputGraph> graphs; private List<InputGraph> graphs;
private transient ChangedEvent<Group> changedEvent; private transient ChangedEvent<Group> changedEvent;

View File

@ -23,26 +23,25 @@
*/ */
package com.sun.hotspot.igv.data; package com.sun.hotspot.igv.data;
import com.sun.hotspot.igv.data.Properties; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class InputGraph extends Properties.Object { public class InputGraph extends Properties.Entity {
private Map<Integer, InputNode> nodes; private HashMap<Integer, InputNode> nodes;
private Set<InputEdge> edges; private ArrayList<InputEdge> edges;
private Group parent; private Group parent;
private Map<String, InputBlock> blocks; private HashMap<String, InputBlock> blocks;
private Map<Integer, InputBlock> nodeToBlock; private HashMap<Integer, InputBlock> nodeToBlock;
private boolean isDifferenceGraph; private boolean isDifferenceGraph;
public InputGraph(Group parent) { public InputGraph(Group parent) {
@ -61,10 +60,10 @@ public class InputGraph extends Properties.Object {
public InputGraph(Group parent, InputGraph last, String name) { public InputGraph(Group parent, InputGraph last, String name) {
this.parent = parent; this.parent = parent;
setName(name); setName(name);
nodes = new Hashtable<Integer, InputNode>(); nodes = new HashMap<Integer, InputNode>();
edges = new HashSet<InputEdge>(); edges = new ArrayList<InputEdge>();
blocks = new Hashtable<String, InputBlock>(); blocks = new HashMap<String, InputBlock>();
nodeToBlock = new Hashtable<Integer, InputBlock>(); nodeToBlock = new HashMap<Integer, InputBlock>();
if (last != null) { if (last != null) {
for (InputNode n : last.getNodes()) { for (InputNode n : last.getNodes()) {
@ -182,8 +181,8 @@ public class InputGraph extends Properties.Object {
return nodes.remove(index); return nodes.remove(index);
} }
public Set<InputEdge> getEdges() { public Collection<InputEdge> getEdges() {
return Collections.unmodifiableSet(edges); return Collections.unmodifiableList(edges);
} }
public void removeEdge(InputEdge c) { public void removeEdge(InputEdge c) {

View File

@ -32,7 +32,7 @@ import java.util.List;
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class InputMethod extends Properties.Object { public class InputMethod extends Properties.Entity {
private String name; private String name;
private int bci; private int bci;

View File

@ -27,7 +27,7 @@ package com.sun.hotspot.igv.data;
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class InputNode extends Properties.Object { public class InputNode extends Properties.Entity {
private int id; private int id;

View File

@ -26,24 +26,22 @@ package com.sun.hotspot.igv.data;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Iterator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class Properties implements Serializable { public class Properties implements Serializable, Iterable<Property> {
public static final long serialVersionUID = 1L; public static final long serialVersionUID = 1L;
private Map<String, Property> map; private String[] map = new String[4];
public Properties() { public Properties() {
map = new HashMap<String, Property>(5);
} }
@Override @Override
@ -54,10 +52,7 @@ public class Properties implements Serializable {
Properties p = (Properties) o; Properties p = (Properties) o;
if (getProperties().size() != p.getProperties().size()) { for (Property prop : this) {
return false;
}
for (Property prop : getProperties()) {
String value = p.get(prop.getName()); String value = p.get(prop.getName());
if (value == null || !value.equals(prop.getValue())) { if (value == null || !value.equals(prop.getValue())) {
return false; return false;
@ -75,32 +70,33 @@ public class Properties implements Serializable {
public Properties(String name, String value) { public Properties(String name, String value) {
this(); this();
this.add(new Property(name, value)); this.setProperty(name, value);
} }
public Properties(String name, String value, String name1, String value1) { public Properties(String name, String value, String name1, String value1) {
this(name, value); 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) { public Properties(String name, String value, String name1, String value1, String name2, String value2) {
this(name, value, name1, value1); this(name, value, name1, value1);
this.add(new Property(name2, value2)); this.setProperty(name2, value2);
} }
public Properties(Properties p) { public Properties(Properties p) {
map = new HashMap<String, Property>(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; private Properties properties;
public Object() { public Entity() {
properties = new Properties(); properties = new Properties();
} }
public Object(Properties.Object object) { public Entity(Properties.Entity object) {
properties = new Properties(object.getProperties()); 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 { public interface PropertyMatcher {
String getName(); String getName();
@ -173,13 +177,15 @@ public class Properties implements Serializable {
} }
public Property selectSingle(PropertyMatcher matcher) { public Property selectSingle(PropertyMatcher matcher) {
String value = null;
Property p = this.map.get(matcher.getName()); for (int i = 0; i < map.length; i += 2) {
if (p == null) { if (map[i] != null && matcher.getName().equals(map[i])) {
return null; value = map[i + 1];
break;
}
} }
if (matcher.match(p.getValue())) { if (value != null && matcher.match(value)) {
return p; return new Property(matcher.getName(), value);
} else { } else {
return null; return null;
} }
@ -194,8 +200,11 @@ public class Properties implements Serializable {
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("["); sb.append("[");
for (Property p : map.values()) { for (int i = 0; i < map.length; i += 2) {
sb.append(p.toString()); if (map[i + 1] != null) {
String p = map[i + 1];
sb.append(map[i] + " = " + map[i + 1] + "; ");
}
} }
return sb.append("]").toString(); return sb.append("]").toString();
} }
@ -241,41 +250,51 @@ public class Properties implements Serializable {
} }
public String get(String key) { public String get(String key) {
Property p = map.get(key); for (int i = 0; i < map.length; i += 2) {
if (p == null) { if (map[i] != null && map[i].equals(key)) {
return null; return map[i + 1];
} 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);
} }
return p;
} }
return null;
} }
public Collection<Property> getProperties() { public void setProperty(String name, String value) {
return Collections.unmodifiableCollection(map.values()); 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<Property> getProperties() {
return iterator();
} }
public void add(Properties properties) { public void add(Properties properties) {
for (Property p : properties.getProperties()) { for (Property p : properties) {
add(p); add(p);
} }
} }
@ -283,6 +302,35 @@ public class Properties implements Serializable {
public void add(Property property) { public void add(Property property) {
assert property.getName() != null; assert property.getName() != null;
assert property.getValue() != null; assert property.getValue() != null;
map.put(property.getName(), property); setProperty(property.getName(), property.getValue());
}
class PropertiesIterator implements Iterator<Property>, Iterable<Property> {
public Iterator<Property> 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<Property> iterator() {
return new PropertiesIterator();
} }
} }

View File

@ -32,18 +32,19 @@ import java.io.Serializable;
public class Property implements Serializable { public class Property implements Serializable {
public static final long serialVersionUID = 1L; public static final long serialVersionUID = 1L;
private String name; private String name;
private String value; private String value;
public Property() { private Property() {
this(null, null); this(null, null);
} }
public Property(Property p) { private Property(Property p) {
this(p.getName(), p.getValue()); this(p.getName(), p.getValue());
} }
public Property(String name) { private Property(String name) {
this(name, null); this(name, null);
} }
@ -60,16 +61,19 @@ public class Property implements Serializable {
return value; return value;
} }
public void setName(String s) {
this.name = s;
}
public void setValue(String s) {
this.value = s;
}
@Override @Override
public String toString() { public String toString() {
return name + " = " + value + "; "; 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();
}
} }

View File

@ -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.ParseMonitor;
import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler; import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.XMLReader; import org.xml.sax.XMLReader;
@ -88,6 +89,18 @@ public class Parser {
private TopElementHandler xmlDocument = new TopElementHandler(); private TopElementHandler xmlDocument = new TopElementHandler();
private boolean difference; private boolean difference;
private GroupCallback groupCallback; private GroupCallback groupCallback;
private HashMap<String, Integer> idCache = new HashMap<String, Integer>();
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();
}
// <graphDocument> // <graphDocument>
private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) { private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) {
@ -187,13 +200,13 @@ public class Parser {
previous = null; previous = null;
} }
InputGraph curGraph = new InputGraph(getParentObject(), previous, name); InputGraph curGraph = new InputGraph(getParentObject(), previous, name);
getParentObject().addGraph(curGraph);
this.graph = curGraph; this.graph = curGraph;
return curGraph; return curGraph;
} }
@Override @Override
protected void end(String text) throws SAXException { protected void end(String text) throws SAXException {
getParentObject().addGraph(graph);
graph.resolveBlockLinks(); graph.resolveBlockLinks();
} }
}; };
@ -207,7 +220,7 @@ public class Parser {
@Override @Override
protected InputBlock start() throws SAXException { protected InputBlock start() throws SAXException {
InputGraph graph = getParentObject(); InputGraph graph = getParentObject();
String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); String name = readRequiredAttribute(BLOCK_NAME_PROPERTY).intern();
InputBlock b = new InputBlock(getParentObject(), name); InputBlock b = new InputBlock(getParentObject(), name);
graph.addBlock(b); graph.addBlock(b);
return b; return b;
@ -224,7 +237,7 @@ public class Parser {
int id = 0; int id = 0;
try { try {
id = Integer.parseInt(s); id = lookupID(s);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SAXException(e); throw new SAXException(e);
} }
@ -252,7 +265,7 @@ public class Parser {
String s = readRequiredAttribute(NODE_ID_PROPERTY); String s = readRequiredAttribute(NODE_ID_PROPERTY);
int id = 0; int id = 0;
try { try {
id = Integer.parseInt(s); id = lookupID(s);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SAXException(e); throw new SAXException(e);
} }
@ -269,7 +282,7 @@ public class Parser {
String s = readRequiredAttribute(NODE_ID_PROPERTY); String s = readRequiredAttribute(NODE_ID_PROPERTY);
int id = 0; int id = 0;
try { try {
id = Integer.parseInt(s); id = lookupID(s);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SAXException(e); throw new SAXException(e);
} }
@ -280,7 +293,7 @@ public class Parser {
private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<InputGraph>(EDGES_ELEMENT); private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<InputGraph>(EDGES_ELEMENT);
// Local class for edge elements // Local class for edge elements
private static class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> { private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> {
public EdgeElementHandler(String name) { public EdgeElementHandler(String name) {
super(name); super(name);
@ -298,8 +311,8 @@ public class Parser {
toIndex = Integer.parseInt(toIndexString); toIndex = Integer.parseInt(toIndexString);
} }
from = Integer.parseInt(readRequiredAttribute(FROM_PROPERTY)); from = lookupID(readRequiredAttribute(FROM_PROPERTY));
to = Integer.parseInt(readRequiredAttribute(TO_PROPERTY)); to = lookupID(readRequiredAttribute(TO_PROPERTY));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SAXException(e); throw new SAXException(e);
} }
@ -344,18 +357,16 @@ public class Parser {
} }
}; };
// <property> // <property>
private ElementHandler<Property, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<Property, Properties.Provider>(PROPERTY_ELEMENT, true) { private ElementHandler<String, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<String, Properties.Provider>(PROPERTY_ELEMENT, true) {
@Override @Override
public Property start() throws SAXException { public String start() throws SAXException {
String value = ""; return readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern();
String name = readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern();
return getParentObject().getProperties().setProperty(name, value);
} }
@Override @Override
public void end(String text) { public void end(String text) {
getObject().setValue(text.trim().intern()); getParentObject().getProperties().setProperty(getObject(), text.trim().intern());
} }
}; };

View File

@ -67,7 +67,7 @@ public class Printer {
private void export(XMLWriter writer, Group g) throws IOException { private void export(XMLWriter writer, Group g) throws IOException {
Properties attributes = new Properties(); 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.startTag(Parser.GROUP_ELEMENT, attributes);
writer.writeProperties(g.getProperties()); writer.writeProperties(g.getProperties());

View File

@ -25,7 +25,7 @@ package com.sun.hotspot.igv.data.serialization;
import com.sun.hotspot.igv.data.Property; import com.sun.hotspot.igv.data.Property;
import com.sun.hotspot.igv.data.Properties; import com.sun.hotspot.igv.data.Properties;
import java.util.Hashtable; import java.util.HashMap;
import java.util.Stack; import java.util.Stack;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler; import org.xml.sax.ContentHandler;
@ -89,7 +89,7 @@ public class XMLParser implements ContentHandler {
private Attributes attr; private Attributes attr;
private StringBuilder currentText; private StringBuilder currentText;
private ParseMonitor monitor; private ParseMonitor monitor;
private Hashtable<String, ElementHandler<?, ? super T>> hashtable; private HashMap<String, ElementHandler<?, ? super T>> hashtable;
private boolean needsText; private boolean needsText;
private ElementHandler<P, ?> parentElement; private ElementHandler<P, ?> parentElement;
@ -110,7 +110,7 @@ public class XMLParser implements ContentHandler {
} }
public ElementHandler(String name, boolean needsText) { public ElementHandler(String name, boolean needsText) {
this.hashtable = new Hashtable<String, ElementHandler<?, ? super T>>(); this.hashtable = new HashMap<String, ElementHandler<?, ? super T>>();
this.name = name; this.name = name;
this.needsText = needsText; this.needsText = needsText;
} }
@ -153,7 +153,7 @@ public class XMLParser implements ContentHandler {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
String val = attr.getValue(i).intern(); String val = attr.getValue(i).intern();
String localName = attr.getLocalName(i).intern(); String localName = attr.getLocalName(i).intern();
p.add(new Property(val, localName)); p.setProperty(val, localName);
} }
} }

View File

@ -89,7 +89,7 @@ public class XMLWriter extends Writer {
inner.write("<" + name); inner.write("<" + name);
elementStack.push(name); elementStack.push(name);
for (Property p : attributes.getProperties()) { for (Property p : attributes) {
inner.write(" " + p.getName() + "=\""); inner.write(" " + p.getName() + "=\"");
write(p.getValue().toCharArray()); write(p.getValue().toCharArray());
inner.write("\""); inner.write("\"");
@ -101,7 +101,7 @@ public class XMLWriter extends Writer {
public void simpleTag(String name, Properties attributes) throws IOException { public void simpleTag(String name, Properties attributes) throws IOException {
inner.write("<" + name); inner.write("<" + name);
for (Property p : attributes.getProperties()) { for (Property p : attributes) {
inner.write(" " + p.getName() + "=\""); inner.write(" " + p.getName() + "=\"");
write(p.getValue().toCharArray()); write(p.getValue().toCharArray());
inner.write("\""); inner.write("\"");
@ -111,13 +111,13 @@ public class XMLWriter extends Writer {
} }
public void writeProperties(Properties props) throws IOException { public void writeProperties(Properties props) throws IOException {
if (props.getProperties().size() == 0) { if (props.getProperties().hasNext() == false) {
return; return;
} }
startTag(Parser.PROPERTIES_ELEMENT); 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())); startTag(Parser.PROPERTY_ELEMENT, new Properties(Parser.PROPERTY_NAME_PROPERTY, p.getName()));
this.write(p.getValue().toCharArray()); this.write(p.getValue().toCharArray());
endTag(); endTag();

View File

@ -29,6 +29,7 @@ import com.sun.hotspot.igv.data.InputEdge;
import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.InputNode; import com.sun.hotspot.igv.data.InputNode;
import com.sun.hotspot.igv.data.Property; import com.sun.hotspot.igv.data.Property;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -124,8 +125,8 @@ public class Difference {
inputNodeMap.put(n, n2); inputNodeMap.put(n, n2);
} }
Set<InputEdge> edgesA = a.getEdges(); Collection<InputEdge> edgesA = a.getEdges();
Set<InputEdge> edgesB = b.getEdges(); Collection<InputEdge> edgesB = b.getEdges();
Set<InputEdge> newEdges = new HashSet<InputEdge>(); Set<InputEdge> newEdges = new HashSet<InputEdge>();
@ -182,7 +183,7 @@ public class Difference {
public double getValue() { public double getValue() {
double result = 0.0; double result = 0.0;
for (Property p : n1.getProperties().getProperties()) { for (Property p : n1.getProperties()) {
double faktor = 1.0; double faktor = 1.0;
for (String forbidden : IGNORE_PROPERTIES) { for (String forbidden : IGNORE_PROPERTIES) {
if (p.getName().equals(forbidden)) { if (p.getName().equals(forbidden)) {
@ -287,34 +288,34 @@ public class Difference {
private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) { private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) {
boolean difference = false; boolean difference = false;
for (Property p : otherNode.getProperties().getProperties()) { for (Property p : otherNode.getProperties()) {
String s = firstNode.getProperties().getProperty(p.getName()); String s = firstNode.getProperties().get(p.getName());
if (!p.getValue().equals(s)) { if (!p.getValue().equals(s)) {
difference = true; 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()) { for (Property p : firstNode.getProperties()) {
String s = otherNode.getProperties().getProperty(p.getName()); String s = otherNode.getProperties().get(p.getName());
if (s == null && p.getValue().length() > 0) { if (s == null && p.getValue().length() > 0) {
difference = true; difference = true;
n.getProperties().add(new Property(OLD_PREFIX + p.getName(), "")); n.getProperties().setProperty(OLD_PREFIX + p.getName(), "");
} }
} }
if (difference) { if (difference) {
n.getProperties().add(new Property(PROPERTY_STATE, VALUE_CHANGED)); n.getProperties().setProperty(PROPERTY_STATE, VALUE_CHANGED);
} else { } else {
n.getProperties().add(new Property(PROPERTY_STATE, VALUE_SAME)); n.getProperties().setProperty(PROPERTY_STATE, VALUE_SAME);
} }
} }
private static void markAsDeleted(InputNode n) { 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) { private static void markAsNew(InputNode n) {
n.getProperties().add(new Property(PROPERTY_STATE, VALUE_NEW)); n.getProperties().setProperty(PROPERTY_STATE, VALUE_NEW);
} }
} }

View File

@ -1,6 +1,6 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
OpenIDE-Module: com.sun.hotspot.igv.filter OpenIDE-Module: com.sun.hotspot.igv.filter
OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml
OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0 OpenIDE-Module-Specification-Version: 1.0

View File

@ -25,7 +25,6 @@
package com.sun.hotspot.igv.filter; package com.sun.hotspot.igv.filter;
import com.sun.hotspot.igv.graph.Diagram; import com.sun.hotspot.igv.graph.Diagram;
import com.sun.hotspot.igv.data.Property;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -56,7 +55,7 @@ public class CustomFilter extends AbstractFilter {
public CustomFilter(String name, String code) { public CustomFilter(String name, String code) {
this.name = name; this.name = name;
this.code = code; this.code = code;
getProperties().add(new Property("name", name)); getProperties().setProperty("name", name);
} }
public String getName() { public String getName() {

View File

@ -56,8 +56,8 @@ public class SplitFilter extends AbstractFilter {
for (OutputSlot os : f.getOutputSlots()) { for (OutputSlot os : f.getOutputSlots()) {
for (Connection c : os.getConnections()) { for (Connection c : os.getConnections()) {
InputSlot is = c.getInputSlot(); InputSlot is = c.getInputSlot();
is.setName(f.getProperties().getProperty("dump_spec")); is.setName(f.getProperties().get("dump_spec"));
String s = f.getProperties().getProperty("short_name"); String s = f.getProperties().get("short_name");
if (s != null) { if (s != null) {
is.setShortName(s); is.setShortName(s);
} }

View File

@ -35,7 +35,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -126,7 +126,7 @@ public class Diagram {
d.updateBlocks(); d.updateBlocks();
Collection<InputNode> nodes = graph.getNodes(); Collection<InputNode> nodes = graph.getNodes();
Hashtable<Integer, Figure> figureHash = new Hashtable<Integer, Figure>(); HashMap<Integer, Figure> figureHash = new HashMap<Integer, Figure>();
for (InputNode n : nodes) { for (InputNode n : nodes) {
Figure f = d.createFigure(); Figure f = d.createFigure();
f.getSource().addSourceNode(n); f.getSource().addSourceNode(n);

View File

@ -42,7 +42,7 @@ import java.util.Set;
* *
* @author Thomas Wuerthinger * @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 INSET = 6;
public static final int SLOT_WIDTH = 10; public static final int SLOT_WIDTH = 10;

View File

@ -26,7 +26,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Hashtable; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
@ -37,13 +37,13 @@ import java.util.Queue;
*/ */
public class Graph<N, E> { public class Graph<N, E> {
private Hashtable<Object, Node<N, E>> nodes; private HashMap<Object, Node<N, E>> nodes;
private Hashtable<Object, Edge<N, E>> edges; private HashMap<Object, Edge<N, E>> edges;
private List<Node<N, E>> nodeList; private List<Node<N, E>> nodeList;
public Graph() { public Graph() {
nodes = new Hashtable<Object, Node<N, E>>(); nodes = new HashMap<Object, Node<N, E>>();
edges = new Hashtable<Object, Edge<N, E>>(); edges = new HashMap<Object, Edge<N, E>>();
nodeList = new ArrayList<Node<N, E>>(); nodeList = new ArrayList<Node<N, E>>();
} }

View File

@ -25,7 +25,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.util.Hashtable; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.ArrayList; import java.util.ArrayList;
@ -69,19 +69,19 @@ public class HierarchicalClusterLayoutManager implements LayoutManager {
assert graph.verify(); assert graph.verify();
Hashtable<Cluster, List<Vertex>> lists = new Hashtable<Cluster, List<Vertex>>(); HashMap<Cluster, List<Vertex>> lists = new HashMap<Cluster, List<Vertex>>();
Hashtable<Cluster, List<Link>> listsConnection = new Hashtable<Cluster, List<Link>>(); HashMap<Cluster, List<Link>> listsConnection = new HashMap<Cluster, List<Link>>();
Hashtable<Cluster, Hashtable<Port, ClusterInputSlotNode>> clusterInputSlotHash = new Hashtable<Cluster, Hashtable<Port, ClusterInputSlotNode>>(); HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>> clusterInputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>>();
Hashtable<Cluster, Hashtable<Port, ClusterOutputSlotNode>> clusterOutputSlotHash = new Hashtable<Cluster, Hashtable<Port, ClusterOutputSlotNode>>(); HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>> clusterOutputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>>();
Hashtable<Cluster, ClusterNode> clusterNodes = new Hashtable<Cluster, ClusterNode>(); HashMap<Cluster, ClusterNode> clusterNodes = new HashMap<Cluster, ClusterNode>();
Hashtable<Cluster, Set<ClusterInputSlotNode>> clusterInputSlotSet = new Hashtable<Cluster, Set<ClusterInputSlotNode>>(); HashMap<Cluster, Set<ClusterInputSlotNode>> clusterInputSlotSet = new HashMap<Cluster, Set<ClusterInputSlotNode>>();
Hashtable<Cluster, Set<ClusterOutputSlotNode>> clusterOutputSlotSet = new Hashtable<Cluster, Set<ClusterOutputSlotNode>>(); HashMap<Cluster, Set<ClusterOutputSlotNode>> clusterOutputSlotSet = new HashMap<Cluster, Set<ClusterOutputSlotNode>>();
Set<Link> clusterEdges = new HashSet<Link>(); Set<Link> clusterEdges = new HashSet<Link>();
Set<Link> interClusterEdges = new HashSet<Link>(); Set<Link> interClusterEdges = new HashSet<Link>();
Hashtable<Link, ClusterOutgoingConnection> linkClusterOutgoingConnection = new Hashtable<Link, ClusterOutgoingConnection>(); HashMap<Link, ClusterOutgoingConnection> linkClusterOutgoingConnection = new HashMap<Link, ClusterOutgoingConnection>();
Hashtable<Link, InterClusterConnection> linkInterClusterConnection = new Hashtable<Link, InterClusterConnection>(); HashMap<Link, InterClusterConnection> linkInterClusterConnection = new HashMap<Link, InterClusterConnection>();
Hashtable<Link, ClusterIngoingConnection> linkClusterIngoingConnection = new Hashtable<Link, ClusterIngoingConnection>(); HashMap<Link, ClusterIngoingConnection> linkClusterIngoingConnection = new HashMap<Link, ClusterIngoingConnection>();
Set<ClusterNode> clusterNodeSet = new HashSet<ClusterNode>(); Set<ClusterNode> clusterNodeSet = new HashSet<ClusterNode>();
Set<Cluster> cluster = graph.getClusters(); Set<Cluster> cluster = graph.getClusters();
@ -89,8 +89,8 @@ public class HierarchicalClusterLayoutManager implements LayoutManager {
for (Cluster c : cluster) { for (Cluster c : cluster) {
lists.put(c, new ArrayList<Vertex>()); lists.put(c, new ArrayList<Vertex>());
listsConnection.put(c, new ArrayList<Link>()); listsConnection.put(c, new ArrayList<Link>());
clusterInputSlotHash.put(c, new Hashtable<Port, ClusterInputSlotNode>()); clusterInputSlotHash.put(c, new HashMap<Port, ClusterInputSlotNode>());
clusterOutputSlotHash.put(c, new Hashtable<Port, ClusterOutputSlotNode>()); clusterOutputSlotHash.put(c, new HashMap<Port, ClusterOutputSlotNode>());
clusterOutputSlotSet.put(c, new TreeSet<ClusterOutputSlotNode>()); clusterOutputSlotSet.put(c, new TreeSet<ClusterOutputSlotNode>());
clusterInputSlotSet.put(c, new TreeSet<ClusterInputSlotNode>()); clusterInputSlotSet.put(c, new TreeSet<ClusterInputSlotNode>());
ClusterNode cn = new ClusterNode(c, "" + z); ClusterNode cn = new ClusterNode(c, "" + z);

View File

@ -24,7 +24,7 @@
package com.sun.hotspot.igv.layout; package com.sun.hotspot.igv.layout;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.HashMap;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -37,9 +37,9 @@ public class LayoutGraph {
private Set<? extends Link> links; private Set<? extends Link> links;
private SortedSet<Vertex> vertices; private SortedSet<Vertex> vertices;
private Hashtable<Vertex, Set<Port>> inputPorts; private HashMap<Vertex, Set<Port>> inputPorts;
private Hashtable<Vertex, Set<Port>> outputPorts; private HashMap<Vertex, Set<Port>> outputPorts;
private Hashtable<Port, Set<Link>> portLinks; private HashMap<Port, Set<Link>> portLinks;
public LayoutGraph(Set<? extends Link> links) { public LayoutGraph(Set<? extends Link> links) {
this(links, new HashSet<Vertex>()); this(links, new HashSet<Vertex>());
@ -50,9 +50,9 @@ public class LayoutGraph {
assert verify(); assert verify();
vertices = new TreeSet<Vertex>(); vertices = new TreeSet<Vertex>();
portLinks = new Hashtable<Port, Set<Link>>(); portLinks = new HashMap<Port, Set<Link>>();
inputPorts = new Hashtable<Vertex, Set<Port>>(); inputPorts = new HashMap<Vertex, Set<Port>>();
outputPorts = new Hashtable<Vertex, Set<Port>>(); outputPorts = new HashMap<Vertex, Set<Port>>();
for (Link l : links) { for (Link l : links) {
Port p = l.getFrom(); Port p = l.getFrom();

View File

@ -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 was the primary target of the tool. The tool itself is fairly general
with only a few modules that contain C2 specific elements. 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 infrastructure and so requires NetBeans to build. It currently
requires Java 6 to run as it needs support for JavaScript for its requires Java 6 to run as it needs support for JavaScript for its
filtering mechanism and assumes it's built into the platform. It 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 should build out of the box with NetBeans 6.1 and Java 6 or later.
possible to run it on 1.5 by including Rhino on the classpath though It's possible to run it on 1.5 by including Rhino on the classpath
that currently isn't working correctly. Support for exporting graphs though that currently isn't working correctly. Support for exporting
as SVG can be enabled by adding batik to the classpath which isn't graphs as SVG can be enabled by adding batik to the classpath which
included by default. 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.
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.
The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=# The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=#
where # is: where # is:

View File

@ -36,11 +36,11 @@ import org.openide.nodes.Sheet;
*/ */
public class PropertiesSheet { 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(); Sheet.Set set1 = Sheet.createPropertiesSet();
set1.setDisplayName("Properties"); set1.setDisplayName("Properties");
for (final Property p : properties.getProperties()) { for (final Property p : properties) {
Node.Property<String> prop = new Node.Property<String>(String.class) { Node.Property<String> prop = new Node.Property<String>(String.class) {
@Override @Override
@ -60,7 +60,7 @@ public class PropertiesSheet {
@Override @Override
public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
p.setValue(arg0); properties.setProperty(p.getName(), arg0);
} }
}; };
prop.setName(p.getName()); prop.setName(p.getName());

View File

@ -65,13 +65,19 @@ public class RangeSliderModel implements ChangedEventProvider<RangeSliderModel>
public RangeSliderModel(List<String> positions) { public RangeSliderModel(List<String> positions) {
assert positions.size() > 0; assert positions.size() > 0;
this.positions = positions;
this.changedEvent = new ChangedEvent<RangeSliderModel>(this); this.changedEvent = new ChangedEvent<RangeSliderModel>(this);
this.colorChangedEvent = new ChangedEvent<RangeSliderModel>(this); this.colorChangedEvent = new ChangedEvent<RangeSliderModel>(this);
setPositions(positions);
}
protected void setPositions(List<String> positions) {
this.positions = positions;
colors = new ArrayList<Color>(); colors = new ArrayList<Color>();
for (int i = 0; i < positions.size(); i++) { for (int i = 0; i < positions.size(); i++) {
colors.add(Color.black); colors.add(Color.black);
} }
changedEvent.fire();
colorChangedEvent.fire();
} }
public void setColors(List<Color> colors) { public void setColors(List<Color> colors) {

View File

@ -63,7 +63,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -104,10 +104,10 @@ import org.openide.util.lookup.InstanceContent;
*/ */
public class DiagramScene extends Scene implements ChangedListener<DiagramViewModel> { public class DiagramScene extends Scene implements ChangedListener<DiagramViewModel> {
private Hashtable<Figure, FigureWidget> figureWidgets; private HashMap<Figure, FigureWidget> figureWidgets;
private Hashtable<Slot, SlotWidget> slotWidgets; private HashMap<Slot, SlotWidget> slotWidgets;
private Hashtable<Connection, ConnectionWidget> connectionWidgets; private HashMap<Connection, ConnectionWidget> connectionWidgets;
private Hashtable<InputBlock, BlockWidget> blockWidgets; private HashMap<InputBlock, BlockWidget> blockWidgets;
private Widget hoverWidget; private Widget hoverWidget;
private WidgetAction hoverAction; private WidgetAction hoverAction;
private List<FigureWidget> selectedWidgets; private List<FigureWidget> selectedWidgets;
@ -414,7 +414,7 @@ public class DiagramScene extends Scene implements ChangedListener<DiagramViewMo
this.addChild(selectLayer); this.addChild(selectLayer);
this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider)); this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider));
blockWidgets = new Hashtable<InputBlock, BlockWidget>(); blockWidgets = new HashMap<InputBlock, BlockWidget>();
boolean b = this.getUndoRedoEnabled(); boolean b = this.getUndoRedoEnabled();
this.setUndoRedoEnabled(false); this.setUndoRedoEnabled(false);
@ -543,9 +543,9 @@ public class DiagramScene extends Scene implements ChangedListener<DiagramViewMo
blockLayer.removeChildren(); blockLayer.removeChildren();
blockWidgets.clear(); blockWidgets.clear();
figureWidgets = new Hashtable<Figure, FigureWidget>(); figureWidgets = new HashMap<Figure, FigureWidget>();
slotWidgets = new Hashtable<Slot, SlotWidget>(); slotWidgets = new HashMap<Slot, SlotWidget>();
connectionWidgets = new Hashtable<Connection, ConnectionWidget>(); connectionWidgets = new HashMap<Connection, ConnectionWidget>();
WidgetAction selectAction = new ExtendedSelectAction(selectProvider); WidgetAction selectAction = new ExtendedSelectAction(selectProvider);
Diagram d = getModel().getDiagramToView(); Diagram d = getModel().getDiagramToView();

View File

@ -55,6 +55,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
private FilterChain filterChain; private FilterChain filterChain;
private FilterChain sequenceFilterChain; private FilterChain sequenceFilterChain;
private Diagram diagram; private Diagram diagram;
private ChangedEvent<DiagramViewModel> groupChangedEvent;
private ChangedEvent<DiagramViewModel> diagramChangedEvent; private ChangedEvent<DiagramViewModel> diagramChangedEvent;
private ChangedEvent<DiagramViewModel> viewChangedEvent; private ChangedEvent<DiagramViewModel> viewChangedEvent;
private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent; private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
@ -67,6 +68,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
} }
}; };
@Override
public DiagramViewModel copy() { public DiagramViewModel copy() {
DiagramViewModel result = new DiagramViewModel(group, filterChain, sequenceFilterChain); DiagramViewModel result = new DiagramViewModel(group, filterChain, sequenceFilterChain);
result.setData(this); result.setData(this);
@ -79,6 +81,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
boolean viewChanged = false; boolean viewChanged = false;
boolean viewPropertiesChanged = false; boolean viewPropertiesChanged = false;
boolean groupChanged = (group == newModel.group);
this.group = newModel.group; this.group = newModel.group;
diagramChanged |= (filterChain != newModel.filterChain); diagramChanged |= (filterChain != newModel.filterChain);
this.filterChain = newModel.filterChain; this.filterChain = newModel.filterChain;
@ -97,6 +100,10 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull); viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
this.showNodeHull = newModel.showNodeHull; this.showNodeHull = newModel.showNodeHull;
if(groupChanged) {
groupChangedEvent.fire();
}
if (diagramChanged) { if (diagramChanged) {
diagramChangedEvent.fire(); diagramChangedEvent.fire();
} }
@ -143,11 +150,38 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
diagramChangedEvent = new ChangedEvent<DiagramViewModel>(this); diagramChangedEvent = new ChangedEvent<DiagramViewModel>(this);
viewChangedEvent = new ChangedEvent<DiagramViewModel>(this); viewChangedEvent = new ChangedEvent<DiagramViewModel>(this);
viewPropertiesChangedEvent = new ChangedEvent<DiagramViewModel>(this); viewPropertiesChangedEvent = new ChangedEvent<DiagramViewModel>(this);
groupChangedEvent = new ChangedEvent<DiagramViewModel>(this);
groupChangedEvent.addListener(groupChangedListener);
groupChangedEvent.fire();
filterChain.getChangedEvent().addListener(filterChainChangedListener); filterChain.getChangedEvent().addListener(filterChainChangedListener);
sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener); sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
} }
private final ChangedListener<DiagramViewModel> groupChangedListener = new ChangedListener<DiagramViewModel>() {
private Group oldGroup;
public void changed(DiagramViewModel source) {
if(oldGroup != null) {
oldGroup.getChangedEvent().removeListener(groupContentChangedListener);
}
group.getChangedEvent().addListener(groupContentChangedListener);
oldGroup = group;
}
};
private final ChangedListener<Group> groupContentChangedListener = new ChangedListener<Group>() {
public void changed(Group source) {
assert source == group;
setPositions(calculateStringList(source));
setSelectedNodes(selectedNodes);
}
};
public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() { public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() {
return diagramChangedEvent; return diagramChangedEvent;
} }
@ -268,7 +302,10 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
} }
public InputGraph getSecondGraph() { public InputGraph getSecondGraph() {
return group.getGraphs().get(getSecondPosition()); List<InputGraph> graphs = group.getGraphs();
if (graphs.size() >= getSecondPosition())
return group.getGraphs().get(getSecondPosition());
return getFirstGraph();
} }
public void selectGraph(InputGraph g) { public void selectGraph(InputGraph g) {

View File

@ -67,7 +67,7 @@ class FindPanel extends JPanel implements KeyListener {
for (Figure f : figures) { for (Figure f : figures) {
Properties prop = f.getProperties(); Properties prop = f.getProperties();
for (Property p : prop.getProperties()) { for (Property p : prop) {
if (!propertyNames.contains(p.getName())) { if (!propertyNames.contains(p.getName())) {
propertyNames.add(p.getName()); propertyNames.add(p.getName());
} }

View File

@ -1,16 +1,16 @@
# Deprecated since 5.0u1; for compatibility with 5.0: # Deprecated since 5.0u1; for compatibility with 5.0:
disabled.clusters=\ disabled.clusters=\
apisupport1,\ apisupport1,\
gsf1,\
harness,\ harness,\
ide8,\ ide9,\
java1,\ java2,\
nb6.0,\ nb6.1,\
profiler2 profiler3
disabled.modules=\ disabled.modules=\
org.netbeans.core.execution,\ org.netbeans.core.execution,\
org.netbeans.core.multiview,\ org.netbeans.core.multiview,\
org.netbeans.core.output2,\ org.netbeans.core.output2,\
org.netbeans.modules.applemenu,\
org.netbeans.modules.autoupdate.services,\ org.netbeans.modules.autoupdate.services,\
org.netbeans.modules.autoupdate.ui,\ org.netbeans.modules.autoupdate.ui,\
org.netbeans.modules.core.kit,\ org.netbeans.modules.core.kit,\
@ -24,6 +24,6 @@ disabled.modules=\
org.openide.execution,\ org.openide.execution,\
org.openide.util.enumerations org.openide.util.enumerations
enabled.clusters=\ enabled.clusters=\
platform7 platform8
nbjdk.active=default nbjdk.active=default
nbplatform.active=default nbplatform.active=default

View File

@ -15,7 +15,6 @@ modules=\
${project.com.sun.hotspot.igv.difference}:\ ${project.com.sun.hotspot.igv.difference}:\
${project.com.sun.hotspot.igv.settings}:\ ${project.com.sun.hotspot.igv.settings}:\
${project.com.sun.hotspot.igv.util}:\ ${project.com.sun.hotspot.igv.util}:\
${project.com.sun.hotspot.igv.rhino}:\
${project.com.sun.hotspot.igv.svg}:\ ${project.com.sun.hotspot.igv.svg}:\
${project.com.sun.hotspot.connection}:\ ${project.com.sun.hotspot.connection}:\
${project.com.sun.hotspot.igv.servercompilerscheduler}:\ ${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.graph=Graph
project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout
project.com.sun.hotspot.igv.layout=Layout 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.servercompilerscheduler=ServerCompiler
project.com.sun.hotspot.igv.settings=Settings project.com.sun.hotspot.igv.settings=Settings
project.com.sun.hotspot.igv.svg=BatikSVGProxy project.com.sun.hotspot.igv.svg=BatikSVGProxy
project.com.sun.hotspot.igv.view=View project.com.sun.hotspot.igv.view=View
project.com.sun.hotspot.igv.util=Util 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

View File

@ -33,7 +33,6 @@ ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc)
_globalNames(archDesc.globalNames()) { _globalNames(archDesc.globalNames()) {
_AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
_AD._warnings = 0; // No warnings either _AD._warnings = 0; // No warnings either
_linenum = 0; // Will increment to first line
_curline = _ptr = NULL; // No pointers into buffer yet _curline = _ptr = NULL; // No pointers into buffer yet
_preproc_depth = 0; _preproc_depth = 0;
@ -76,7 +75,7 @@ ADLParser::~ADLParser() {
} }
if (!_AD._quiet_mode) if (!_AD._quiet_mode)
fprintf(stderr,"-----------------------------------------------------------------------------\n"); 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 // Write out information we have stored
// // UNIXism == fsync(stderr); // // UNIXism == fsync(stderr);
@ -148,7 +147,7 @@ void ADLParser::instr_parse(void) {
if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL ) if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
return; return;
instr = new InstructForm(ident); // Create new instruction form instr = new InstructForm(ident); // Create new instruction form
instr->_linenum = _linenum; instr->_linenum = linenum();
_globalNames.Insert(ident, instr); // Add name to the name table _globalNames.Insert(ident, instr); // Add name to the name table
// Debugging Stuff // Debugging Stuff
if (_AD._adl_debug > 1) if (_AD._adl_debug > 1)
@ -404,7 +403,7 @@ void ADLParser::oper_parse(void) {
if( (ident = get_unique_ident(_globalNames,"operand")) == NULL ) if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
return; return;
oper = new OperandForm(ident); // Create new operand form oper = new OperandForm(ident); // Create new operand form
oper->_linenum = _linenum; oper->_linenum = linenum();
_globalNames.Insert(ident, oper); // Add name to the name table _globalNames.Insert(ident, oper); // Add name to the name table
// Debugging Stuff // Debugging Stuff
@ -774,7 +773,7 @@ void ADLParser::reg_parse(void) {
// Create the RegisterForm for the architecture description. // Create the RegisterForm for the architecture description.
RegisterForm *regBlock = new RegisterForm(); // Build new Source object RegisterForm *regBlock = new RegisterForm(); // Build new Source object
regBlock->_linenum = _linenum; regBlock->_linenum = linenum();
_AD.addForm(regBlock); _AD.addForm(regBlock);
skipws(); // Skip leading whitespace skipws(); // Skip leading whitespace
@ -847,7 +846,7 @@ void ADLParser::enc_class_parse(void) {
} }
EncClass *encoding = _AD._encode->add_EncClass(ec_name); EncClass *encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = _linenum; encoding->_linenum = linenum();
skipws(); // Skip leading whitespace skipws(); // Skip leading whitespace
// Check for optional parameter list // 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 // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) { if (_AD._adlocation_debug) {
const char* file = _AD._ADL_file._name; const char* file = _AD._ADL_file._name;
int line = _linenum; int line = linenum();
char* location = (char *)malloc(strlen(file) + 100); char* location = (char *)malloc(strlen(file) + 100);
sprintf(location, "#line %d \"%s\"\n", line, file); sprintf(location, "#line %d \"%s\"\n", line, file);
encoding->add_code(location); 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"); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
EncClass *encoding = _AD._encode->add_EncClass(ec_name); EncClass *encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = _linenum; encoding->_linenum = linenum();
// synthesize the arguments list for the enc_class from the // synthesize the arguments list for the enc_class from the
// arguments to the instruct definition. // arguments to the instruct definition.
@ -2852,7 +2851,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
skipws(); skipws();
InsEncode *encrule = new InsEncode(); // Encode class for instruction InsEncode *encrule = new InsEncode(); // Encode class for instruction
encrule->_linenum = _linenum; encrule->_linenum = linenum();
char *ec_name = NULL; // String representation of encode rule char *ec_name = NULL; // String representation of encode rule
// identifier is optional. // identifier is optional.
while (_curchar != ')') { while (_curchar != ')') {
@ -3203,6 +3202,12 @@ Interface *ADLParser::cond_interface_parse(void) {
char *greater_equal; char *greater_equal;
char *less_equal; char *less_equal;
char *greater; 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 != '%') { if (_curchar != '%') {
parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
@ -3222,22 +3227,22 @@ Interface *ADLParser::cond_interface_parse(void) {
return NULL; return NULL;
} }
if ( strcmp(field,"equal") == 0 ) { if ( strcmp(field,"equal") == 0 ) {
equal = interface_field_parse(); equal = interface_field_parse(&equal_format);
} }
else if ( strcmp(field,"not_equal") == 0 ) { else if ( strcmp(field,"not_equal") == 0 ) {
not_equal = interface_field_parse(); not_equal = interface_field_parse(&not_equal_format);
} }
else if ( strcmp(field,"less") == 0 ) { else if ( strcmp(field,"less") == 0 ) {
less = interface_field_parse(); less = interface_field_parse(&less_format);
} }
else if ( strcmp(field,"greater_equal") == 0 ) { 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 ) { 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 ) { else if ( strcmp(field,"greater") == 0 ) {
greater = interface_field_parse(); greater = interface_field_parse(&greater_format);
} }
else { else {
parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); 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 '}' next_char(); // Skip '}'
// Construct desired object and return // Construct desired object and return
Interface *inter = new CondInterface(equal, not_equal, less, greater_equal, Interface *inter = new CondInterface(equal, equal_format,
less_equal, greater); not_equal, not_equal_format,
less, less_format,
greater_equal, greater_equal_format,
less_equal, less_equal_format,
greater, greater_format);
return inter; return inter;
} }
//------------------------------interface_field_parse-------------------------- //------------------------------interface_field_parse--------------------------
char *ADLParser::interface_field_parse(void) { char *ADLParser::interface_field_parse(const char ** format) {
char *iface_field = NULL; char *iface_field = NULL;
// Get interface field // Get interface field
@ -3280,6 +3289,32 @@ char *ADLParser::interface_field_parse(void) {
return NULL; return NULL;
} }
skipws(); 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 != ')') { if (_curchar != ')') {
parse_err(SYNERR, "Missing ')' after interface field.\n"); parse_err(SYNERR, "Missing ')' after interface field.\n");
return NULL; return NULL;
@ -3342,6 +3377,12 @@ FormatRule* ADLParser::format_parse(void) {
next_char(); // Move past the '{' next_char(); // Move past the '{'
skipws(); 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 // Check for the opening '"' inside the format description
if ( _curchar == '"' ) { if ( _curchar == '"' ) {
next_char(); // Move past the initial '"' 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" <newline> "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----------------------------------- //------------------------------effect_parse-----------------------------------
void ADLParser::effect_parse(InstructForm *instr) { void ADLParser::effect_parse(InstructForm *instr) {
char* desc = NULL; char* desc = NULL;
@ -3777,7 +3943,7 @@ char* ADLParser::find_cpp_block(const char* description) {
skipws_no_preproc(); // Skip leading whitespace skipws_no_preproc(); // Skip leading whitespace
cppBlock = _ptr; // Point to start of expression cppBlock = _ptr; // Point to start of expression
const char* file = _AD._ADL_file._name; const char* file = _AD._ADL_file._name;
int line = _linenum; int line = linenum();
next = _ptr + 1; next = _ptr + 1;
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) { while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
next_char_or_line(); next_char_or_line();
@ -4297,11 +4463,11 @@ void ADLParser::parse_err(int flag, const char *fmt, ...) {
va_start(args, fmt); va_start(args, fmt);
if (flag == 1) 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) 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 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; int error_char = _curchar;
char* error_ptr = _ptr+1; char* error_ptr = _ptr+1;
@ -4515,7 +4681,7 @@ void ADLParser::next_char_or_line() {
//---------------------------next_line----------------------------------------- //---------------------------next_line-----------------------------------------
void ADLParser::next_line() { void ADLParser::next_line() {
_curline = _buf.get_line(); _linenum++; _curline = _buf.get_line();
} }
//-------------------------is_literal_constant--------------------------------- //-------------------------is_literal_constant---------------------------------

View File

@ -70,7 +70,6 @@ class ADLParser {
protected: protected:
char *_curline; // Start of current line char *_curline; // Start of current line
char *_ptr; // Pointer into current location in File Buffer char *_ptr; // Pointer into current location in File Buffer
int _linenum; // Count of line numbers seen so far
char _curchar; // Current character from buffer char _curchar; // Current character from buffer
FormDict &_globalNames; // Global names FormDict &_globalNames; // Global names
@ -160,9 +159,10 @@ protected:
Interface *interface_parse(); // Parse operand interface rule Interface *interface_parse(); // Parse operand interface rule
Interface *mem_interface_parse(); // Parse memory interface rule Interface *mem_interface_parse(); // Parse memory interface rule
Interface *cond_interface_parse(); // Parse conditional 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 *format_parse(void); // Parse format rule
FormatRule *template_parse(void); // Parse format rule
void effect_parse(InstructForm *instr); // Parse effect rule void effect_parse(InstructForm *instr); // Parse effect rule
ExpandRule *expand_parse(InstructForm *instr); // Parse expand rule ExpandRule *expand_parse(InstructForm *instr); // Parse expand rule
RewriteRule *rewrite_parse(void); // Parse rewrite rule RewriteRule *rewrite_parse(void); // Parse rewrite rule
@ -263,7 +263,7 @@ public:
void parse(void); // Do the parsing & build forms lists 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_literal_constant(const char *hex_string);
static bool is_hex_digit(char digit); static bool is_hex_digit(char digit);

View File

@ -41,6 +41,7 @@ FileBuff::FileBuff( BufferedFile *fptr, ArchDesc& archDesc) : _fp(fptr), _AD(arc
exit(1); // Exit on seek error exit(1); // Exit on seek error
} }
_filepos = ftell(_fp->_fp); // Reset current file position _filepos = ftell(_fp->_fp); // Reset current file position
_linenum = 0;
_bigbuf = new char[_bufferSize]; // Create buffer to hold text for parser _bigbuf = new char[_bufferSize]; // Create buffer to hold text for parser
if( !_bigbuf ) { if( !_bigbuf ) {
@ -76,6 +77,7 @@ char *FileBuff::get_line(void) {
// Check for end of file & return NULL // Check for end of file & return NULL
if (_bufeol >= _bufmax) return NULL; if (_bufeol >= _bufmax) return NULL;
_linenum++;
retval = ++_bufeol; // return character following end of previous line retval = ++_bufeol; // return character following end of previous line
if (*retval == '\0') return NULL; // Check for EOF sentinal if (*retval == '\0') return NULL; // Check for EOF sentinal
// Search for newline character which must end each line // Search for newline character which must end each line

View File

@ -51,6 +51,7 @@ class FileBuff {
int _err; // Error flag for file seek/read operations int _err; // Error flag for file seek/read operations
long _filepos; // Current offset from start of file long _filepos; // Current offset from start of file
int _linenum;
ArchDesc& _AD; // Reference to Architecture Description 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, // 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. // and increments bufeol and filepos to point at the end of that line.
char *get_line(void); char *get_line(void);
int linenum() const { return _linenum; }
// This converts a pointer into the buffer to a file offset. It only works // 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()). // when the pointer is valid (i.e. just obtained from getline()).

View File

@ -35,6 +35,8 @@ Arena *Form::generate_arena() {
//------------------------------NameList--------------------------------------- //------------------------------NameList---------------------------------------
// reserved user-defined string // reserved user-defined string
const char *NameList::_signal = "$$SIGNAL$$"; const char *NameList::_signal = "$$SIGNAL$$";
const char *NameList::_signal2 = "$$SIGNAL2$$";
const char *NameList::_signal3 = "$$SIGNAL3$$";
// Constructor and Destructor // Constructor and Destructor
NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) { NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) {

View File

@ -329,6 +329,8 @@ protected:
public: public:
static const char *_signal; // reserved user-defined string 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 }; enum { Not_in_list = -1 };
void addName(const char *name); void addName(const char *name);

View File

@ -1574,10 +1574,10 @@ Opcode::opcode_type Opcode::as_opcode_type(const char *param) {
return Opcode::NOT_AN_OPCODE; 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()... // Default values previously provided by MachNode::primary()...
const char *description = "default_opcode()"; const char *description = NULL;
const char *value = "-1"; const char *value = NULL;
// Check if user provided any opcode definitions // Check if user provided any opcode definitions
if( this != NULL ) { if( this != NULL ) {
// Update 'value' if user provided a definition in the instruction // 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; break;
} }
} }
fprintf(fp, "(%s /*%s*/)", value, description); if (value != NULL) {
fprintf(fp, "(%s /*%s*/)", value, description);
}
return value != NULL;
} }
void Opcode::dump() { void Opcode::dump() {
@ -2610,14 +2613,19 @@ void MemInterface::output(FILE *fp) {
} }
//------------------------------CondInterface---------------------------------- //------------------------------CondInterface----------------------------------
CondInterface::CondInterface(char *equal, char *not_equal, CondInterface::CondInterface(const char* equal, const char* equal_format,
char *less, char *greater_equal, const char* not_equal, const char* not_equal_format,
char *less_equal, char *greater) 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"), : Interface("COND_INTER"),
_equal(equal), _not_equal(not_equal), _equal(equal), _equal_format(equal_format),
_less(less), _greater_equal(greater_equal), _not_equal(not_equal), _not_equal_format(not_equal_format),
_less_equal(less_equal), _greater(greater) { _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() { CondInterface::~CondInterface() {
// not owner of any character arrays // 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", "Load8B" ,"Load4B" ,"Load8C" ,"Load4C" ,"Load2C" ,"Load8S", "Load4S","Load2S",
"LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned", "LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",
"LoadPLocked", "LoadLLocked", "LoadPLocked", "LoadLLocked",
"StorePConditional", "StoreLConditional", "StorePConditional", "StoreIConditional", "StoreLConditional",
"CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
"StoreCM", "StoreCM",
"ClearArray" "ClearArray"

View File

@ -397,7 +397,7 @@ public:
void output(FILE *fp); void output(FILE *fp);
// --------------------------- FILE *output_routines // --------------------------- FILE *output_routines
void print_opcode(FILE *fp, Opcode::opcode_type desired_opcode); bool print_opcode(FILE *fp, Opcode::opcode_type desired_opcode);
}; };
//------------------------------InsEncode-------------------------------------- //------------------------------InsEncode--------------------------------------
@ -779,10 +779,20 @@ public:
const char *_greater_equal; const char *_greater_equal;
const char *_less_equal; const char *_less_equal;
const char *_greater; 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 // Public Methods
CondInterface(char *equal, char *not_equal, char *less, char *greater_equal, CondInterface(const char* equal, const char* equal_format,
char *less_equal, char *greater); 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(); ~CondInterface();
void dump(); void dump();

View File

@ -1619,6 +1619,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
} }
// Iterate over the new instruction's operands // Iterate over the new instruction's operands
int prev_pos = -1;
for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) { for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) {
// Use 'parameter' at current position in list of new instruction's formals // Use 'parameter' at current position in list of new instruction's formals
// instead of 'opid' when looking up info internal to new_inst // 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]; // ins = (InstructForm *) _globalNames[new_id];
exp_pos = node->operand_position_format(opid); exp_pos = node->operand_position_format(opid);
assert(exp_pos != -1, "Bad expand rule"); 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); new_pos = new_inst->operand_position(parameter,Component::USE);
if (new_pos != -1) { if (new_pos != -1) {
@ -2306,7 +2319,12 @@ private:
_processing_noninput = false; _processing_noninput = false;
// A replacement variable, originally '$' // A replacement variable, originally '$'
if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) { 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 { else {
// Lookup its position in parameter list // 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 if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) {
// else check if "primary", "secondary", "tertiary" // else check if "primary", "secondary", "tertiary"
assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); 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; _constant_status = LITERAL_OUTPUT;
} }
else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) { else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) {

View File

@ -355,17 +355,19 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Generate the format rule for condition codes // Generate the format rule for condition codes
static void defineCCodeDump(FILE *fp, int i) { static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) {
fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"eq\");\n",i); assert(oper != NULL, "what");
fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"ne\");\n",i); CondInterface* cond = oper->_interface->is_CondInterface();
fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"le\");\n",i); fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"ge\");\n",i); fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"lt\");\n",i); fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"gt\");\n",i); 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 // 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")) { if (!strcmp(ideal_type, "ConI")) {
fprintf(fp," st->print(\"#%%d\", _c%d);\n", i); fprintf(fp," st->print(\"#%%d\", _c%d);\n", i);
++i; ++i;
@ -375,7 +377,7 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) {
++i; ++i;
} }
else if (!strcmp(ideal_type, "ConN")) { else if (!strcmp(ideal_type, "ConN")) {
fprintf(fp," _c%d->dump();\n", i); fprintf(fp," _c%d->dump_on(st);\n", i);
++i; ++i;
} }
else if (!strcmp(ideal_type, "ConL")) { else if (!strcmp(ideal_type, "ConL")) {
@ -391,7 +393,7 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) {
++i; ++i;
} }
else if (!strcmp(ideal_type, "Bool")) { else if (!strcmp(ideal_type, "Bool")) {
defineCCodeDump(fp,i); defineCCodeDump(oper, fp,i);
++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. // ALWAYS! Provide a special case output for condition codes.
if( oper.is_ideal_bool() ) { if( oper.is_ideal_bool() ) {
defineCCodeDump(fp,0); defineCCodeDump(&oper, fp,0);
} }
fprintf(fp,"}\n"); 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. // ALWAYS! Provide a special case output for condition codes.
if( oper.is_ideal_bool() ) { if( oper.is_ideal_bool() ) {
defineCCodeDump(fp,0); defineCCodeDump(&oper, fp,0);
} }
fprintf(fp, "}\n"); fprintf(fp, "}\n");
fprintf(fp, "#endif\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 ) { while( (string = inst._format->_strings.iter()) != NULL ) {
fprintf(fp," "); fprintf(fp," ");
// Check if this is a standard string or a replacement variable // 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); 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 with all format strings
} // Done generating the user-defined portion of the format } // Done generating the user-defined portion of the format
@ -1404,7 +1449,7 @@ void ArchDesc::declareClasses(FILE *fp) {
oper->_components.reset(); oper->_components.reset();
if ((comp = oper->_components.iter()) == NULL) { if ((comp = oper->_components.iter()) == NULL) {
assert(num_consts == 1, "Bad component list detected.\n"); 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 // Check that type actually matched
assert( i != 0, "Non-constant operand lacks component list."); assert( i != 0, "Non-constant operand lacks component list.");
} // end if NULL } // end if NULL
@ -1414,7 +1459,7 @@ void ArchDesc::declareClasses(FILE *fp) {
oper->_components.reset(); oper->_components.reset();
while((comp = oper->_components.iter()) != NULL) { while((comp = oper->_components.iter()) != NULL) {
type = comp->base_type(_globalNames); type = comp->base_type(_globalNames);
i = dump_spec_constant( fp, type, i ); i = dump_spec_constant( fp, type, i, NULL );
} }
} }
// finish line (3) // finish line (3)

View File

@ -28,8 +28,9 @@
Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) { Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) {
assert(!is_last_bytecode(), "should have been checked"); assert(!is_last_bytecode(), "should have been checked");
// set next bytecode position // set next bytecode position
address bcp = RawBytecodeStream::bcp(); address bcp = RawBytecodeStream::bcp();
int l = Bytecodes::raw_special_length_at(bcp); address end = method()->code_base() + end_bci();
int l = Bytecodes::raw_special_length_at(bcp, end);
if (l <= 0 || (_bci + l) > _end_bci) { if (l <= 0 || (_bci + l) > _end_bci) {
code = Bytecodes::_illegal; code = Bytecodes::_illegal;
} else { } else {
@ -39,8 +40,12 @@ Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) {
_is_wide = false; _is_wide = false;
// check for special (uncommon) cases // check for special (uncommon) cases
if (code == Bytecodes::_wide) { if (code == Bytecodes::_wide) {
code = (Bytecodes::Code)bcp[1]; if (bcp + 1 >= end) {
_is_wide = true; code = Bytecodes::_illegal;
} else {
code = (Bytecodes::Code)bcp[1];
_is_wide = true;
}
} }
} }
_code = code; _code = code;

View File

@ -54,13 +54,19 @@ Bytecodes::Code Bytecodes::non_breakpoint_code_at(address bcp, methodOop method)
return method->orig_bytecode_at(method->bci_from(bcp)); 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); Code code = code_at(bcp);
switch (code) { switch (code) {
case _wide: 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))); return wide_length_for(cast(*(bcp + 1)));
case _tableswitch: case _tableswitch:
{ address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize); { 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 lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize);
jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*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_binaryswitch: // fall through
case _fast_linearswitch: case _fast_linearswitch:
{ address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize); { 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 npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize; jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize;
// only return len if it can be represented as a positive int; // 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 // verifier when reading in bytecode to verify. Other mechanisms that
// run at runtime (such as generateOopMaps) need to iterate over the code // 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 // 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. // 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); Code code = code_or_bp_at(bcp);
if (code == _breakpoint) { if (code == _breakpoint) {
return 1; return 1;
} else { } else {
return special_length_at(bcp); return special_length_at(bcp, end);
} }
} }

View File

@ -340,8 +340,10 @@ class Bytecodes: AllStatic {
const char* wf = wide_format(code); const char* wf = wide_format(code);
return (wf == NULL) ? 0 : (int)strlen(wf); return (wf == NULL) ? 0 : (int)strlen(wf);
} }
static int special_length_at(address bcp); // if 'end' is provided, it indicates the end of the code buffer which
static int raw_special_length_at(address bcp); // 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 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 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; } static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; }

View File

@ -57,6 +57,14 @@ void Block_List::insert(uint i, Block *b) {
_blocks[i] = 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 // Check for Start block
if( _pre_order == 1 ) return InteriorEntryAlignment; if( _pre_order == 1 ) return InteriorEntryAlignment;
// Check for loop alignment // Check for loop alignment
if (has_loop_alignment()) return loop_alignment();
return 1; // no particular alignment
}
uint Block::compute_loop_alignment() {
Node *h = head(); Node *h = head();
if( h->is_Loop() && h->as_Loop()->is_inner_loop() ) { if( h->is_Loop() && h->as_Loop()->is_inner_loop() ) {
// Pre- and post-loops have low trip count so do not bother with // 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 OptoLoopAlignment; // Otherwise align loop head
} }
return 1; // no particular alignment return 1; // no particular alignment
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Compute the size of first 'inst_cnt' instructions in this block. // Compute the size of first 'inst_cnt' instructions in this block.
// Return the number of instructions left to compute if the block has // 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, uint Block::compute_first_inst_size(uint& sum_size, uint inst_cnt,
PhaseRegAlloc* ra) { PhaseRegAlloc* ra) {
uint last_inst = _nodes.size(); 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); tty->print("\tLoop: B%d-B%d ", bhead->_pre_order, bx->_pre_order);
// Dump any loop-specific bits, especially for CountedLoops. // Dump any loop-specific bits, especially for CountedLoops.
loop->dump_spec(tty); loop->dump_spec(tty);
} else if (has_loop_alignment()) {
tty->print(" top-of-loop");
} }
tty->print(" Freq: %g",_freq); tty->print(" Freq: %g",_freq);
if( Verbose || WizardMode ) { if( Verbose || WizardMode ) {
@ -509,9 +527,11 @@ static bool no_flip_branch( Block *b ) {
int branch_idx = b->_nodes.size() - b->_num_succs-1; int branch_idx = b->_nodes.size() - b->_num_succs-1;
if( branch_idx < 1 ) return false; if( branch_idx < 1 ) return false;
Node *bra = b->_nodes[branch_idx]; 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_Mach() ) {
if( bra->is_MachNullCheck() ) return true; if( bra->is_MachNullCheck() )
return true;
int iop = bra->as_Mach()->ideal_Opcode(); int iop = bra->as_Mach()->ideal_Opcode();
if( iop == Op_FastLock || iop == Op_FastUnlock ) if( iop == Op_FastLock || iop == Op_FastUnlock )
return true; return true;
@ -557,10 +577,10 @@ void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) {
dead->_nodes[k]->del_req(j); dead->_nodes[k]->del_req(j);
} }
//------------------------------MoveToNext------------------------------------- //------------------------------move_to_next-----------------------------------
// Helper function to move block bx to the slot following b_index. Return // Helper function to move block bx to the slot following b_index. Return
// true if the move is successful, otherwise false // 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; if (bx == NULL) return false;
// Return false if bx is already scheduled. // Return false if bx is already scheduled.
@ -591,9 +611,9 @@ bool PhaseCFG::MoveToNext(Block* bx, uint b_index) {
return true; return true;
} }
//------------------------------MoveToEnd-------------------------------------- //------------------------------move_to_end------------------------------------
// Move empty and uncommon blocks to the 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(); int e = b->is_Empty();
if (e != Block::not_empty) { if (e != Block::not_empty) {
if (e == Block::empty_with_goto) { if (e == Block::empty_with_goto) {
@ -609,15 +629,31 @@ void PhaseCFG::MoveToEnd(Block *b, uint i) {
_blocks.push(b); _blocks.push(b);
} }
//------------------------------RemoveEmpty------------------------------------ //---------------------------set_loop_alignment--------------------------------
// Remove empty basic blocks and useless branches. // Set loop alignment for every block
void PhaseCFG::RemoveEmpty() { 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 // Move uncommon blocks to the end
uint last = _num_blocks; uint last = _num_blocks;
uint i;
assert( _blocks[0] == _broot, "" ); assert( _blocks[0] == _broot, "" );
for( i = 1; i < last; i++ ) {
for (uint i = 1; i < last; i++) {
Block *b = _blocks[i]; Block *b = _blocks[i];
if (b->is_connector()) break;
// Check for NeverBranch at block end. This needs to become a GOTO to the // Check for NeverBranch at block end. This needs to become a GOTO to the
// true target. NeverBranch are treated as a conditional branch that // true target. NeverBranch are treated as a conditional branch that
@ -629,37 +665,40 @@ void PhaseCFG::RemoveEmpty() {
convert_NeverBranch_to_Goto(b); convert_NeverBranch_to_Goto(b);
// Look for uncommon blocks and move to end. // Look for uncommon blocks and move to end.
if( b->is_uncommon(_bbs) ) { if (!C->do_freq_based_layout()) {
MoveToEnd(b, i); if( b->is_uncommon(_bbs) ) {
last--; // No longer check for being uncommon! move_to_end(b, i);
if( no_flip_branch(b) ) { // Fall-thru case must follow? last--; // No longer check for being uncommon!
b = _blocks[i]; // Find the fall-thru block if( no_flip_branch(b) ) { // Fall-thru case must follow?
MoveToEnd(b, i); b = _blocks[i]; // Find the fall-thru block
last--; move_to_end(b, i);
last--;
}
i--; // backup block counter post-increment
} }
i--; // backup block counter post-increment
} }
} }
// Remove empty blocks // Move empty blocks to the end
uint j1;
last = _num_blocks; last = _num_blocks;
for( i=0; i < last; i++ ) { for (uint i = 1; i < last; i++) {
Block *b = _blocks[i]; Block *b = _blocks[i];
if (i > 0) { if (b->is_Empty() != Block::not_empty) {
if (b->is_Empty() != Block::not_empty) { move_to_end(b, i);
MoveToEnd(b, i); last--;
last--; i--;
i--;
}
} }
} // End of for all blocks } // 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 // Fixup final control flow for the blocks. Remove jump-to-next
// block. If neither arm of a IF follows the conditional branch, we // block. If neither arm of a IF follows the conditional branch, we
// have to add a second jump after the conditional. We place the // have to add a second jump after the conditional. We place the
// TRUE branch target in succs[0] for both GOTOs and IFs. // 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]; Block *b = _blocks[i];
b->_pre_order = i; // turn pre-order into block-index b->_pre_order = i; // turn pre-order into block-index
@ -700,7 +739,7 @@ void PhaseCFG::RemoveEmpty() {
} }
} }
// Remove all CatchProjs // 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) { } else if (b->_num_succs == 1) {
// Block ends in a Goto? // Block ends in a Goto?
@ -730,8 +769,7 @@ void PhaseCFG::RemoveEmpty() {
// successors after the current one, provided that the // successors after the current one, provided that the
// successor was previously unscheduled, but moveable // successor was previously unscheduled, but moveable
// (i.e., all paths to it involve a branch). // (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 // Choose the more common successor based on the probability
// of the conditional branch. // of the conditional branch.
Block *bx = bs0; Block *bx = bs0;
@ -751,9 +789,9 @@ void PhaseCFG::RemoveEmpty() {
} }
// Attempt the more common successor first // Attempt the more common successor first
if (MoveToNext(bx, i)) { if (move_to_next(bx, i)) {
bnext = bx; bnext = bx;
} else if (MoveToNext(by, i)) { } else if (move_to_next(by, i)) {
bnext = by; bnext = by;
} }
} }
@ -774,10 +812,8 @@ void PhaseCFG::RemoveEmpty() {
// Flip projection for each target // Flip projection for each target
{ ProjNode *tmp = proj0; proj0 = proj1; proj1 = tmp; } { ProjNode *tmp = proj0; proj0 = proj1; proj1 = tmp; }
} else if( bnext == bs1 ) { // Fall-thru is already in succs[1] } else if( bnext != bs1 ) {
// Need a double-branch
} else { // Else need a double-branch
// The existing conditional branch need not change. // The existing conditional branch need not change.
// Add a unconditional branch to the false target. // Add a unconditional branch to the false target.
// Alas, it must appear in its own block and adding a // 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 // Make sure we TRUE branch to the target
if( proj0->Opcode() == Op_IfFalse ) if( proj0->Opcode() == Op_IfFalse ) {
iff->negate(); iff->negate();
}
b->_nodes.pop(); // Remove IfFalse & IfTrue projections b->_nodes.pop(); // Remove IfFalse & IfTrue projections
b->_nodes.pop(); b->_nodes.pop();
@ -796,9 +833,7 @@ void PhaseCFG::RemoveEmpty() {
// Multi-exit block, e.g. a switch statement // Multi-exit block, e.g. a switch statement
// But we don't need to do anything here // But we don't need to do anything here
} }
} // End of for all blocks } // 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 // Force the Union-Find mapping to be at least this large
extend(max,0); extend(max,0);
// Initialize to be the ID mapping. // Initialize to be the ID mapping.
for( uint i=0; i<_max; i++ ) map(i,i); for( uint i=0; i<max; i++ ) map(i,i);
} }
//------------------------------Find_compress---------------------------------- //------------------------------Find_compress----------------------------------
@ -937,7 +972,6 @@ uint UnionFind::Find_const( uint idx ) const {
if( idx >= _max ) return idx; if( idx >= _max ) return idx;
uint next = lookup(idx); uint next = lookup(idx);
while( next != idx ) { // Scan chain of equivalences while( next != idx ) { // Scan chain of equivalences
assert( next < idx, "always union smaller" );
idx = next; // until find a fixed-point idx = next; // until find a fixed-point
next = lookup(idx); next = lookup(idx);
} }
@ -956,3 +990,491 @@ void UnionFind::Union( uint idx1, uint idx2 ) {
assert( src < dst, "always union smaller" ); assert( src < dst, "always union smaller" );
map(dst,src); map(dst,src);
} }
#ifndef PRODUCT
static void edge_dump(GrowableArray<CFGEdge *> *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<CFGEdge*>;
// 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);
}
}
}
}
}
}

View File

@ -75,6 +75,7 @@ public:
void insert( uint i, Block *n ); void insert( uint i, Block *n );
uint size() const { return _cnt; } uint size() const { return _cnt; }
void reset() { _cnt = 0; } void reset() { _cnt = 0; }
void print();
}; };
@ -129,7 +130,11 @@ class Block : public CFGElement {
uint _rpo; // Number in reverse post order walk uint _rpo; // Number in reverse post order walk
virtual bool is_block() { return true; } 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. Block* dom_lca(Block* that); // Compute LCA in dominator tree.
#ifdef ASSERT #ifdef ASSERT
@ -144,6 +149,7 @@ class Block : public CFGElement {
// Report the alignment required by this block. Must be a power of 2. // Report the alignment required by this block. Must be a power of 2.
// The previous block will insert nops to get this alignment. // The previous block will insert nops to get this alignment.
uint code_alignment(); uint code_alignment();
uint compute_loop_alignment();
// BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies. // BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies.
// It is currently also used to scale such frequencies relative to // 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; int current_alignment = current_offset & max_pad;
if( current_alignment != 0 ) { if( current_alignment != 0 ) {
uint padding = (block_alignment-current_alignment) & max_pad; uint padding = (block_alignment-current_alignment) & max_pad;
if( !head()->is_Loop() || if( has_loop_alignment() &&
padding <= (uint)MaxLoopPad || padding > (uint)MaxLoopPad &&
first_inst_size() > padding ) { first_inst_size() <= padding ) {
return padding; return 0;
} }
return padding;
} }
} }
return 0; return 0;
@ -202,6 +209,21 @@ class Block : public CFGElement {
void set_connector() { _connector = true; } void set_connector() { _connector = true; }
bool is_connector() const { return _connector; }; 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. // Create a new Block with given head Node.
// Creates the (empty) predecessor arrays. // Creates the (empty) predecessor arrays.
Block( Arena *a, Node *headnode ) Block( Arena *a, Node *headnode )
@ -219,7 +241,8 @@ class Block : public CFGElement {
_raise_LCA_mark(0), _raise_LCA_mark(0),
_raise_LCA_visited(0), _raise_LCA_visited(0),
_first_inst_size(999999), _first_inst_size(999999),
_connector(false) { _connector(false),
_loop_alignment(0) {
_nodes.push(headnode); _nodes.push(headnode);
} }
@ -275,6 +298,16 @@ class Block : public CFGElement {
return s; 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 // Successor block, after forwarding through connectors
Block* non_connector_successor(int i) const { Block* non_connector_successor(int i) const {
return _succs[i]->non_connector(); 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. // I'll need a few machine-specific GotoNodes. Clone from this one.
MachNode *_goto; MachNode *_goto;
void insert_goto_at(uint block_no, uint succ_no);
Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false); Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false);
void verify_anti_dependences(Block* LCA, Node* load) { 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 // Compute the instruction global latency with a backwards walk
void ComputeLatenciesBackwards(VectorSet &visited, Node_List &stack); void ComputeLatenciesBackwards(VectorSet &visited, Node_List &stack);
// Set loop alignment
void set_loop_alignment();
// Remove empty basic blocks // Remove empty basic blocks
void RemoveEmpty(); void remove_empty();
bool MoveToNext(Block* bx, uint b_index); void fixup_flow();
void MoveToEnd(Block* bx, uint b_index); 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 // 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 // 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. // Map Block indices to a block-index for a cfg-cover.
// Array lookup in the optimized case. // Array lookup in the optimized case.
class UnionFind : public ResourceObj { class UnionFind : public ResourceObj {
@ -508,3 +545,166 @@ class CFGLoop : public CFGElement {
void dump_tree() const; void dump_tree() const;
#endif #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<CFGEdge *> *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);
};

View File

@ -388,6 +388,9 @@
product(intx, EliminateAllocationArraySizeLimit, 64, \ product(intx, EliminateAllocationArraySizeLimit, 64, \
"Array size (number of elements) limit for scalar replacement") \ "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, \ product(intx, ValueSearchLimit, 1000, \
"Recursion limit in PhaseMacroExpand::value_from_mem_phi") \ "Recursion limit in PhaseMacroExpand::value_from_mem_phi") \
\ \
@ -396,5 +399,15 @@
\ \
diagnostic(intx, DominatorSearchLimit, 1000, \ diagnostic(intx, DominatorSearchLimit, 1000, \
"Iterations limit in Node::dominates") \ "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) C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)

View File

@ -967,6 +967,7 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp,
init_class_id(Class_SafePointScalarObject); init_class_id(Class_SafePointScalarObject);
} }
bool SafePointScalarObjectNode::pinned() const { return true; }
uint SafePointScalarObjectNode::ideal_reg() const { uint SafePointScalarObjectNode::ideal_reg() const {
return 0; // No matching to machine instruction return 0; // No matching to machine instruction

View File

@ -433,6 +433,10 @@ public:
uint n_fields() const { return _n_fields; } uint n_fields() const { return _n_fields; }
DEBUG_ONLY(AllocateNode* alloc() const { return _alloc; }) 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); } virtual uint size_of() const { return sizeof(*this); }
// Assumes that "this" is an argument to a safepoint node "s", and that // Assumes that "this" is an argument to a safepoint node "s", and that

View File

@ -440,9 +440,7 @@ void PhaseChaitin::Register_Allocate() {
assert((int)(_matcher._new_SP+_framesize) >= (int)_matcher._out_arg_limit, "framesize must be large enough"); assert((int)(_matcher._new_SP+_framesize) >= (int)_matcher._out_arg_limit, "framesize must be large enough");
// This frame must preserve the required fp alignment // This frame must preserve the required fp alignment
const int stack_alignment_in_words = Matcher::stack_alignment_in_slots(); _framesize = round_to(_framesize, Matcher::stack_alignment_in_slots());
if (stack_alignment_in_words > 0)
_framesize = round_to(_framesize, Matcher::stack_alignment_in_bytes());
assert( _framesize >= 0 && _framesize <= 1000000, "sanity check" ); assert( _framesize >= 0 && _framesize <= 1000000, "sanity check" );
#ifndef PRODUCT #ifndef PRODUCT
_total_framesize += _framesize; _total_framesize += _framesize;

View File

@ -205,6 +205,7 @@ macro(StoreB)
macro(StoreC) macro(StoreC)
macro(StoreCM) macro(StoreCM)
macro(StorePConditional) macro(StorePConditional)
macro(StoreIConditional)
macro(StoreLConditional) macro(StoreLConditional)
macro(StoreD) macro(StoreD)
macro(StoreF) macro(StoreF)

View File

@ -551,7 +551,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
rethrow_exceptions(kit.transfer_exceptions_into_jvms()); rethrow_exceptions(kit.transfer_exceptions_into_jvms());
} }
print_method("Before RemoveUseless"); print_method("Before RemoveUseless", 3);
// Remove clutter produced by parsing. // Remove clutter produced by parsing.
if (!failing()) { if (!failing()) {
@ -822,6 +822,7 @@ void Compile::Init(int aliaslevel) {
Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist)); Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
set_decompile_count(0); set_decompile_count(0);
set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
// Compilation level related initialization // Compilation level related initialization
if (env()->comp_level() == CompLevel_fast_compile) { if (env()->comp_level() == CompLevel_fast_compile) {
set_num_loop_opts(Tier1LoopOptsCount); 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 // are not adding any new instructions. If any basic block is empty, we
// can now safely remove it. // can now safely remove it.
{ {
NOT_PRODUCT( TracePhase t2("removeEmpty", &_t_removeEmptyBlocks, TimeCompiler); ) NOT_PRODUCT( TracePhase t2("blockOrdering", &_t_blockOrdering, TimeCompiler); )
cfg.RemoveEmpty(); 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. // 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_StorePConditional:
case Op_StoreI: case Op_StoreI:
case Op_StoreL: case Op_StoreL:
case Op_StoreIConditional:
case Op_StoreLConditional: case Op_StoreLConditional:
case Op_CompareAndSwapI: case Op_CompareAndSwapI:
case Op_CompareAndSwapL: case Op_CompareAndSwapL:

View File

@ -154,6 +154,7 @@ class Compile : public Phase {
uint _decompile_count; // Cumulative decompilation counts. uint _decompile_count; // Cumulative decompilation counts.
bool _do_inlining; // True if we intend to do inlining bool _do_inlining; // True if we intend to do inlining
bool _do_scheduling; // True if we intend to do scheduling 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_count_invocations; // True if we generate code to count invocations
bool _do_method_data_update; // True if we generate code to update methodDataOops bool _do_method_data_update; // True if we generate code to update methodDataOops
int _AliasLevel; // Locally-adjusted version of AliasLevel flag. 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; } void set_do_inlining(bool z) { _do_inlining = z; }
bool do_scheduling() const { return _do_scheduling; } bool do_scheduling() const { return _do_scheduling; }
void set_do_scheduling(bool z) { _do_scheduling = z; } 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; } bool do_count_invocations() const{ return _do_count_invocations; }
void set_do_count_invocations(bool z){ _do_count_invocations = z; } void set_do_count_invocations(bool z){ _do_count_invocations = z; }
bool do_method_data_update() const { return _do_method_data_update; } bool do_method_data_update() const { return _do_method_data_update; }

View File

@ -1319,11 +1319,33 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_
//------------------------------Estimate_Block_Frequency----------------------- //------------------------------Estimate_Block_Frequency-----------------------
// Estimate block frequencies based on IfNode probabilities. // Estimate block frequencies based on IfNode probabilities.
void PhaseCFG::Estimate_Block_Frequency() { 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 // Force conditional branches leading to uncommon traps to be unlikely,
// negative so make sure cnts is a sane value. // not because we get to the uncommon_trap with less relative frequency,
if( cnts <= 0 ) cnts = 1; // but because an uncommon_trap typically causes a deopt, so we only get
float f = (float)cnts/(float)FreqCountInvocations; // 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. // Create the loop tree and calculate loop depth.
_root_loop = create_loop_tree(); _root_loop = create_loop_tree();
@ -1333,27 +1355,29 @@ void PhaseCFG::Estimate_Block_Frequency() {
_root_loop->compute_freq(); _root_loop->compute_freq();
// Adjust all frequencies to be relative to a single method entry // 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(); _root_loop->scale_freq();
// force paths ending at uncommon traps to be infrequent // force paths ending at uncommon traps to be infrequent
Block_List worklist; if (!C->do_freq_based_layout()) {
Block* root_blk = _blocks[0]; Block_List worklist;
for (uint i = 0; i < root_blk->num_preds(); i++) { Block* root_blk = _blocks[0];
Block *pb = _bbs[root_blk->pred(i)->_idx]; for (uint i = 1; i < root_blk->num_preds(); i++) {
if (pb->has_uncommon_code()) { Block *pb = _bbs[root_blk->pred(i)->_idx];
worklist.push(pb); if (pb->has_uncommon_code()) {
}
}
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) {
worklist.push(pb); 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 #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, // For all loops other than the outer, "method" loop,
// sum and normalize the exit probability. The "method" loop // sum and normalize the exit probability. The "method" loop
// should keep the initial exit probability of 1, so that // 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. // the probability of exit per loop entry.
for (int i = 0; i < _exits.length(); i++) { for (int i = 0; i < _exits.length(); i++) {
Block* et = _exits.at(i).get_target(); 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); BlockProbPair bpp(et, new_prob);
_exits.at_put(i, bpp); _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. // as the value is used to estimate the loop trip count.
// An infinite trip count would blur relative block // An infinite trip count would blur relative block
// frequencies. // frequencies.
@ -1688,6 +1699,137 @@ float Block::succ_prob(uint i) {
return 0.0f; 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_succ_freq-------------------------------
// Update the appropriate frequency associated with block 'b', a succesor of // Update the appropriate frequency associated with block 'b', a succesor of
// a block in this loop. // a block in this loop.

View File

@ -3485,11 +3485,32 @@ bool LibraryCallKit::inline_native_AtomicLong_attemptUpdate() {
const TypePtr *adr_type = _gvn.type(adr)->is_ptr(); const TypePtr *adr_type = _gvn.type(adr)->is_ptr();
int alias_idx = C->get_alias_index(adr_type); 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 *cas = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal));
Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(result)); Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(cas));
set_memory(store_proj, alias_idx); 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; return true;
} }

View File

@ -1519,6 +1519,7 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
Node *bol = iff->in(1); Node *bol = iff->in(1);
if( bol && bol->req() > 1 && bol->in(1) && if( bol && bol->req() > 1 && bol->in(1) &&
((bol->in(1)->Opcode() == Op_StorePConditional ) || ((bol->in(1)->Opcode() == Op_StorePConditional ) ||
(bol->in(1)->Opcode() == Op_StoreIConditional ) ||
(bol->in(1)->Opcode() == Op_StoreLConditional ) || (bol->in(1)->Opcode() == Op_StoreLConditional ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapI ) || (bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapL ) || (bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||

View File

@ -82,16 +82,31 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal
} }
} }
Node* PhaseMacroExpand::opt_iff(Node* region, Node* iff) { Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) {
IfNode *opt_iff = transform_later(iff)->as_If(); 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 // Fast path taken.
Node *fast_taken = transform_later( new (C, 1) IfFalseNode(opt_iff) ); Node *fast_taken = transform_later( new (C, 1) IfFalseNode(iff) );
region->init_req(2,fast_taken); // Capture fast-control
// Fast path not-taken, i.e. slow path // Fast path not-taken, i.e. slow path
Node *slow_taken = transform_later( new (C, 1) IfTrueNode(opt_iff) ); Node *slow_taken = transform_later( new (C, 1) IfTrueNode(iff) );
return slow_taken;
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-------------------- //--------------------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* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) {
Node* adr = basic_plus_adr(base, offset); 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); Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt);
transform_later(value); transform_later(value);
return value; return value;
@ -1583,12 +1598,194 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
Node* flock = lock->fastlock_node(); Node* flock = lock->fastlock_node();
// Make the merge point // 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)); if (UseOptoBiasInlining) {
Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN ); /*
// Optimize test; set region slot 2 * See the full descrition in MacroAssembler::biased_locking_enter().
Node *slow_path = opt_iff(region,iff); *
* 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 // 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 ); 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); transform_later(region);
_igvn.subsume_node(_fallthroughproj, region); _igvn.subsume_node(_fallthroughproj, region);
// create a Phi for the memory state Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
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(1, memproj );
mem_phi->init_req(2, mem);
transform_later(mem_phi); transform_later(mem_phi);
_igvn.hash_delete(_memproj_fallthrough); _igvn.hash_delete(_memproj_fallthrough);
_igvn.subsume_node(_memproj_fallthrough, mem_phi); _igvn.subsume_node(_memproj_fallthrough, mem_phi);
} }
//------------------------------expand_unlock_node---------------------- //------------------------------expand_unlock_node----------------------
@ -1637,14 +1829,31 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
// No need for a null check on unlock // No need for a null check on unlock
// Make the merge point // 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 ); FastUnlockNode *funlock = new (C, 3) FastUnlockNode( ctrl, obj, box );
funlock = transform_later( funlock )->as_FastUnlock(); 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 // 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 ); 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); transform_later(region);
_igvn.subsume_node(_fallthroughproj, 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(1, memproj );
mem_phi->init_req(2, mem); mem_phi->init_req(2, mem);
transform_later(mem_phi); transform_later(mem_phi);
_igvn.hash_delete(_memproj_fallthrough); _igvn.hash_delete(_memproj_fallthrough);
_igvn.subsume_node(_memproj_fallthrough, mem_phi); _igvn.subsume_node(_memproj_fallthrough, mem_phi);
} }
//------------------------------expand_macro_nodes---------------------- //------------------------------expand_macro_nodes----------------------

View File

@ -93,7 +93,7 @@ private:
int replace_input(Node *use, Node *oldref, Node *newref); int replace_input(Node *use, Node *oldref, Node *newref);
void copy_call_debug_info(CallNode *oldcall, CallNode * newcall); 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); 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, 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); const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1);

View File

@ -1951,6 +1951,7 @@ void Matcher::find_shared( Node *n ) {
// Now hack a few special opcodes // Now hack a few special opcodes
switch( n->Opcode() ) { // Handle some opcodes special switch( n->Opcode() ) { // Handle some opcodes special
case Op_StorePConditional: case Op_StorePConditional:
case Op_StoreIConditional:
case Op_StoreLConditional: case Op_StoreLConditional:
case Op_CompareAndSwapI: case Op_CompareAndSwapI:
case Op_CompareAndSwapL: case Op_CompareAndSwapL:

View File

@ -324,7 +324,7 @@ public:
virtual int regnum_to_fpu_offset(int regnum); virtual int regnum_to_fpu_offset(int regnum);
// Is this branch offset small enough to be addressed by a short branch? // 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. // Optional scaling for the parameter to the ClearArray/CopyArray node.
static const bool init_array_count_is_in_bytes; static const bool init_array_count_is_in_bytes;

View File

@ -227,6 +227,14 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
const Type *t_adr = phase->type( address ); const Type *t_adr = phase->type( address );
if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL 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 // Avoid independent memory operations
Node* old_mem = mem; Node* old_mem = mem;

View File

@ -632,6 +632,17 @@ public:
virtual uint ideal_reg() const { return Op_RegFlags; } 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--------------------------- //------------------------------StoreLConditionalNode---------------------------
// Conditionally store long to memory, if no change since prior // Conditionally store long to memory, if no change since prior
// load-locked. Sets flags for success or failure of the store. // load-locked. Sets flags for success or failure of the store.
@ -639,6 +650,8 @@ class StoreLConditionalNode : public LoadStoreNode {
public: public:
StoreLConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ll ) : LoadStoreNode(c, mem, adr, val, ll) { } StoreLConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ll ) : LoadStoreNode(c, mem, adr, val, ll) { }
virtual int Opcode() const; virtual int Opcode() const;
// Produces flags
virtual uint ideal_reg() const { return Op_RegFlags; }
}; };

View File

@ -263,7 +263,7 @@ bool Compile::is_node_getting_a_safepoint( Node* n) {
# endif // ENABLE_ZAP_DEAD_LOCALS # endif // ENABLE_ZAP_DEAD_LOCALS
//------------------------------compute_loop_first_inst_sizes------------------ //------------------------------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 // 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 // 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. // 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++ ) { for( uint i=1; i <= last_block; i++ ) {
Block *b = _cfg->_blocks[i]; Block *b = _cfg->_blocks[i];
// Check the first loop's block which requires an alignment. // Check the first loop's block which requires an alignment.
if( b->head()->is_Loop() && if( b->loop_alignment() > (uint)relocInfo::addr_unit() ) {
b->code_alignment() > (uint)relocInfo::addr_unit() ) {
uint sum_size = 0; uint sum_size = 0;
uint inst_cnt = NumberOfLoopInstrToAlign; uint inst_cnt = NumberOfLoopInstrToAlign;
inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt, inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt, _regalloc);
_regalloc);
// Check the next fallthrough block if first loop's block does not have // Check subsequent fallthrough blocks if the loop's first
// enough instructions. // block(s) does not have enough instructions.
if( inst_cnt > 0 && i < last_block ) { Block *nb = b;
// First, check if the first loop's block contains whole loop. while( inst_cnt > 0 &&
// LoopNode::LoopBackControl == 2. i < last_block &&
Block *bx = _cfg->_bbs[b->pred(2)->_idx]; !_cfg->_blocks[i+1]->has_loop_alignment() &&
// Skip connector blocks (with limit in case of irreducible loops). !nb->has_successor(b) ) {
int search_limit = 16; i++;
while( bx->is_connector() && search_limit-- > 0) { nb = _cfg->_blocks[i];
bx = _cfg->_bbs[bx->pred(1)->_idx]; inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt, _regalloc);
} } // while( inst_cnt > 0 && i < last_block )
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 )
b->set_first_inst_size(sum_size); b->set_first_inst_size(sum_size);
} // f( b->head()->is_Loop() ) } // f( b->head()->is_Loop() )
} // for( i <= last_block ) } // 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 *jmp_end = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks);
uint *blk_starts = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks+1); 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_target = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); )
DEBUG_ONLY( uint *jmp_rule = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); )
blk_starts[0] = 0; blk_starts[0] = 0;
// Initialize the sizes to 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]; uintptr_t target = blk_starts[bnum];
if( mach->is_pc_relative() ) { if( mach->is_pc_relative() ) {
int offset = target-(blk_starts[i] + jmp_end[i]); 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. // 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); b->_nodes.map(j, replacement);
mach->subsume_by(replacement); mach->subsume_by(replacement);
@ -453,6 +443,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
// next pass. // next pass.
jmp_end[i] -= (mach->size(_regalloc) - replacement->size(_regalloc)); jmp_end[i] -= (mach->size(_regalloc) - replacement->size(_regalloc));
DEBUG_ONLY( jmp_target[i] = bnum; ); DEBUG_ONLY( jmp_target[i] = bnum; );
DEBUG_ONLY( jmp_rule[i] = mach->rule(); );
} }
} else { } else {
#ifndef PRODUCT #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 // Get the size of the block
uint blk_size = adr - blk_starts[i]; 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. // instructions.
Block *nb = _cfg->_blocks[i+1]; Block *nb = _cfg->_blocks[i+1];
int current_offset = blk_starts[i] + blk_size; 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 for( i=0; i<_cfg->_num_blocks; i++ ) { // For all blocks
if( jmp_target[i] != 0 ) { if( jmp_target[i] != 0 ) {
int offset = blk_starts[jmp_target[i]]-(blk_starts[i] + jmp_end[i]); 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]); 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 #endif
@ -1069,7 +1060,7 @@ void Compile::Fill_buffer() {
// If this machine supports different size branch offsets, then pre-compute // If this machine supports different size branch offsets, then pre-compute
// the length of the blocks // 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); Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req);
labels_not_set = false; labels_not_set = false;
} }
@ -1380,8 +1371,8 @@ void Compile::Fill_buffer() {
} // End for all instructions in block } // End for all instructions in block
// If the next block _starts_ a loop, pad this block out to align // If the next block is the top of a loop, pad this block out to align
// the loop start a little. Helps prevent pipe stalls at loop starts // the loop top a little. Helps prevent pipe stalls at loop back branches.
int nop_size = (new (this) MachNopNode())->size(_regalloc); int nop_size = (new (this) MachNopNode())->size(_regalloc);
if( i<_cfg->_num_blocks-1 ) { if( i<_cfg->_num_blocks-1 ) {
Block *nb = _cfg->_blocks[i+1]; Block *nb = _cfg->_blocks[i+1];

View File

@ -46,7 +46,7 @@ elapsedTimer Phase::_t_output;
#ifndef PRODUCT #ifndef PRODUCT
elapsedTimer Phase::_t_graphReshaping; elapsedTimer Phase::_t_graphReshaping;
elapsedTimer Phase::_t_scheduler; elapsedTimer Phase::_t_scheduler;
elapsedTimer Phase::_t_removeEmptyBlocks; elapsedTimer Phase::_t_blockOrdering;
elapsedTimer Phase::_t_macroExpand; elapsedTimer Phase::_t_macroExpand;
elapsedTimer Phase::_t_peephole; elapsedTimer Phase::_t_peephole;
elapsedTimer Phase::_t_codeGeneration; 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 (" 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 (" 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 (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds()); tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.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) + (DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) +
Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() + Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
Phase::_t_matcher.seconds() + Phase::_t_scheduler.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_macroExpand.seconds() + Phase::_t_peephole.seconds() +
Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.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; double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0;

View File

@ -40,16 +40,12 @@ public:
Optimistic, // Optimistic analysis phase Optimistic, // Optimistic analysis phase
GVN, // Pessimistic global value numbering phase GVN, // Pessimistic global value numbering phase
Ins_Select, // Instruction selection 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 CFG, // Build a CFG
DefUse, // Build Def->Use chains BlockLayout, // Linear ordering of blocks
Register_Allocation, // Register allocation, duh Register_Allocation, // Register allocation, duh
LIVE, // Dragon-book LIVE range problem LIVE, // Dragon-book LIVE range problem
Interference_Graph, // Building the IFG Interference_Graph, // Building the IFG
Coalesce, // Coalescing copies Coalesce, // Coalescing copies
Conditional_CProp, // Conditional Constant Propagation
Ideal_Loop, // Find idealized trip-counted loops Ideal_Loop, // Find idealized trip-counted loops
Macro_Expand, // Expand macro nodes Macro_Expand, // Expand macro nodes
Peephole, // Apply peephole optimizations Peephole, // Apply peephole optimizations
@ -80,7 +76,7 @@ protected:
#ifndef PRODUCT #ifndef PRODUCT
static elapsedTimer _t_graphReshaping; static elapsedTimer _t_graphReshaping;
static elapsedTimer _t_scheduler; static elapsedTimer _t_scheduler;
static elapsedTimer _t_removeEmptyBlocks; static elapsedTimer _t_blockOrdering;
static elapsedTimer _t_macroExpand; static elapsedTimer _t_macroExpand;
static elapsedTimer _t_peephole; static elapsedTimer _t_peephole;
static elapsedTimer _t_codeGeneration; static elapsedTimer _t_codeGeneration;

View File

@ -53,6 +53,7 @@ Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) {
// Bail rather than abort // Bail rather than abort
int ireg = def->ideal_reg(); int ireg = def->ideal_reg();
if( ireg == 0 || ireg == Op_RegFlags ) { 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"); C->record_method_not_compilable("attempted to spill a non-spillable item");
return NULL; return NULL;
} }

View File

@ -3541,7 +3541,7 @@ intptr_t TypeNarrowOop::get_con() const {
#ifndef PRODUCT #ifndef PRODUCT
void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const {
tty->print("narrowoop: "); st->print("narrowoop: ");
_ooptype->dump2(d, depth, st); _ooptype->dump2(d, depth, st);
} }
#endif #endif

View File

@ -1183,6 +1183,9 @@ inline bool Type::is_floatingpoint() const {
#define RShiftXNode RShiftLNode #define RShiftXNode RShiftLNode
// For card marks and hashcodes // For card marks and hashcodes
#define URShiftXNode URShiftLNode #define URShiftXNode URShiftLNode
// UseOptoBiasInlining
#define XorXNode XorLNode
#define StoreXConditionalNode StoreLConditionalNode
// Opcodes // Opcodes
#define Op_LShiftX Op_LShiftL #define Op_LShiftX Op_LShiftL
#define Op_AndX Op_AndL #define Op_AndX Op_AndL
@ -1222,6 +1225,9 @@ inline bool Type::is_floatingpoint() const {
#define RShiftXNode RShiftINode #define RShiftXNode RShiftINode
// For card marks and hashcodes // For card marks and hashcodes
#define URShiftXNode URShiftINode #define URShiftXNode URShiftINode
// UseOptoBiasInlining
#define XorXNode XorINode
#define StoreXConditionalNode StoreIConditionalNode
// Opcodes // Opcodes
#define Op_LShiftX Op_LShiftI #define Op_LShiftX Op_LShiftI
#define Op_AndX Op_AndI #define Op_AndX Op_AndI

View File

@ -1365,6 +1365,9 @@ void Arguments::set_aggressive_opts_flags() {
if (AggressiveOpts && FLAG_IS_DEFAULT(SpecialArraysEquals)) { if (AggressiveOpts && FLAG_IS_DEFAULT(SpecialArraysEquals)) {
FLAG_SET_DEFAULT(SpecialArraysEquals, true); FLAG_SET_DEFAULT(SpecialArraysEquals, true);
} }
if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
}
#endif #endif
if (AggressiveOpts) { if (AggressiveOpts) {
@ -2625,6 +2628,12 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
FLAG_SET_DEFAULT(UseBiasedLocking, false); FLAG_SET_DEFAULT(UseBiasedLocking, false);
#endif /* CC_INTERP */ #endif /* CC_INTERP */
#ifdef COMPILER2
if (!UseBiasedLocking || EmitSync != 0) {
UseOptoBiasInlining = false;
}
#endif
if (PrintCommandLineFlags) { if (PrintCommandLineFlags) {
CommandLineFlags::printSetFlags(); CommandLineFlags::printSetFlags();
} }

View File

@ -83,12 +83,12 @@ void RegisterMap::print_on(outputStream* st) const {
intptr_t* src = (intptr_t*) location(r); intptr_t* src = (intptr_t*) location(r);
if (src != NULL) { if (src != NULL) {
r->print(); r->print_on(st);
tty->print(" [" INTPTR_FORMAT "] = ", src); st->print(" [" INTPTR_FORMAT "] = ", src);
if (((uintptr_t)src & (sizeof(*src)-1)) != 0) { if (((uintptr_t)src & (sizeof(*src)-1)) != 0) {
tty->print_cr("<misaligned>"); st->print_cr("<misaligned>");
} else { } else {
tty->print_cr(INTPTR_FORMAT, *src); st->print_cr(INTPTR_FORMAT, *src);
} }
} }
} }

View File

@ -263,7 +263,7 @@ void VMError::report(outputStream* st) {
st->print("# java.lang.OutOfMemoryError: "); st->print("# java.lang.OutOfMemoryError: ");
if (_size) { if (_size) {
st->print("requested "); st->print("requested ");
sprintf(buf,"%d",_size); sprintf(buf,SIZE_FORMAT,_size);
st->print(buf); st->print(buf);
st->print(" bytes"); st->print(" bytes");
if (_message != NULL) { if (_message != NULL) {

View File

@ -13,3 +13,4 @@ eac46d1eb7f0935ba04f1c7929ec15423fd0309e jdk7-b35
c84ca638db42a8b6b227b4e3b63bca192c5ca634 jdk7-b36 c84ca638db42a8b6b227b4e3b63bca192c5ca634 jdk7-b36
af49591bc486d82aa04b832257de0d18adc9af52 jdk7-b37 af49591bc486d82aa04b832257de0d18adc9af52 jdk7-b37
e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38 e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38
831b80be6cea8e7d7da197ccdac5fd4c701a5033 jdk7-b39

View File

@ -13,3 +13,4 @@ b0f01c2508b690dd225298edfec70b5e8b8dc367 jdk7-b35
f60187f44a0d62906a5e2f6bd0989b5b24c1ca1e jdk7-b36 f60187f44a0d62906a5e2f6bd0989b5b24c1ca1e jdk7-b36
a2a6f9edf761934faf59ea60d7fe7178371302cd jdk7-b37 a2a6f9edf761934faf59ea60d7fe7178371302cd jdk7-b37
9ce439969184c753a9ba3caf8ed277b05230f2e5 jdk7-b38 9ce439969184c753a9ba3caf8ed277b05230f2e5 jdk7-b38
077bc9b1b035a409a76bd5366f73ed9dd9846934 jdk7-b39

View File

@ -13,3 +13,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
134fd1a656ea85acd1f97f6700f75029b9b472a0 jdk7-b36 134fd1a656ea85acd1f97f6700f75029b9b472a0 jdk7-b36
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37 14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38 cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38
4e51997582effa006dde5c6d8b8820b2045b9c7f jdk7-b39

View File

@ -44,13 +44,13 @@
<!-- because they depend on the values of BUILD_DATE and BUILD_DATE_SIMPLE --> <!-- because they depend on the values of BUILD_DATE and BUILD_DATE_SIMPLE -->
<!-- At this time, ./build.properties has not been loaded yet. --> <!-- At this time, ./build.properties has not been loaded yet. -->
<property name="project.build.name" value="openjdk-bXX"/> <property name="project.build.name" value="openjdk-bXX"/>
<property name="project.build.fulltag" <property name="project.build.fulltag"
value="${ant.project.name}-${project.build.name}-${BUILD_DATE}" /> value="${ant.project.name}-${project.build.name}-${BUILD_DATE}" />
<!-- unchecked warnings will be fixed in JMX 2.0 as part of the work <!-- unchecked warnings will be fixed in JMX 2.0 as part of the work
being done on JSR 255 new features --> being done on JSR 255 new features -->
<property name="javac.options" <property name="javac.options"
value="-Xlint -Xlint:-unchecked -Xlint:-deprecation"/> value="-Xlint -Xlint:-deprecation"/>
</target> </target>
@ -58,13 +58,13 @@
<!-- Dir to keep generated stub source --> <!-- Dir to keep generated stub source -->
<mkdir dir="${gensrc.dir}" /> <mkdir dir="${gensrc.dir}" />
</target> </target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Call rmic-jmx subtargets --> <!-- Call rmic-jmx subtargets -->
<target name="-rmic-jmx" depends="-init,-rmic-jmx-jrmp,-rmic-jmx-iiop" <target name="-rmic-jmx" depends="-init,-rmic-jmx-jrmp,-rmic-jmx-iiop"
description="Calls -init,-rmic-jmx-jrmp,-rmic-jmx-iiop" description="Calls -init,-rmic-jmx-jrmp,-rmic-jmx-iiop"
/> />
@ -96,7 +96,7 @@
<target name="-rmic-jmx-iiop" depends="-init,-check-jmx-iiop-uptodate" unless="jmx-iiop-uptodate" <target name="-rmic-jmx-iiop" depends="-init,-check-jmx-iiop-uptodate" unless="jmx-iiop-uptodate"
description="Generate RMI IIOP stub class files for remote objects. Do not keep generated java files." > description="Generate RMI IIOP stub class files for remote objects. Do not keep generated java files." >
<rmic base="${classes.dir}" <rmic base="${classes.dir}"
includeAntRuntime="no" includeAntRuntime="no"
includeJavaRuntime="no" includeJavaRuntime="no"
@ -115,11 +115,11 @@
<target name="-check-jmx-iiop-uptodate" depends="-init"> <target name="-check-jmx-iiop-uptodate" depends="-init">
<uptodate property="jmx-iiop-uptodate" <uptodate property="jmx-iiop-uptodate"
srcfile="${classes.dir}/javax/management/remote/rmi/RMIConnectionImpl.class" srcfile="${classes.dir}/javax/management/remote/rmi/RMIConnectionImpl.class"
targetfile="${classes.dir}/org/omg/stub/javax/management/remote/rmi/_RMIConnectionImpl_Tie.class" targetfile="${classes.dir}/org/omg/stub/javax/management/remote/rmi/_RMIConnectionImpl_Tie.class"
/> />
<uptodate property="jmx-iiop-uptodate" <uptodate property="jmx-iiop-uptodate"
srcfile="${classes.dir}/javax/management/remote/rmi/RMIServerImpl.class" srcfile="${classes.dir}/javax/management/remote/rmi/RMIServerImpl.class"
targetfile="${classes.dir}/org/omg/stub/javax/management/remote/rmi/_RMIServerImpl_Tie.class" targetfile="${classes.dir}/org/omg/stub/javax/management/remote/rmi/_RMIServerImpl_Tie.class"
/> />
@ -131,7 +131,7 @@
<target name="-post-compile" depends="-init,-rmic-jmx" <target name="-post-compile" depends="-init,-rmic-jmx"
description="Jar JMX class files (including RMI stubs)" > description="Jar JMX class files (including RMI stubs)" >
<mkdir dir="${dist.dir}/lib"/> <mkdir dir="${dist.dir}/lib"/>
<jar jarfile="${dist.dir}/lib/${jar.jmx.name}" <jar jarfile="${dist.dir}/lib/${jar.jmx.name}"
update="true" update="true"
index="false" index="false"
duplicate="fail"> duplicate="fail">
@ -144,7 +144,7 @@
<attribute name="Specification-Version" value="${jar.jmx.spec.version}" /> <attribute name="Specification-Version" value="${jar.jmx.spec.version}" />
<attribute name="Specification-Vendor" value="${jar.jmx.spec.vendor}" /> <attribute name="Specification-Vendor" value="${jar.jmx.spec.vendor}" />
<attribute name="Implementation-Title" value="${jar.jmx.impl.title}" /> <attribute name="Implementation-Title" value="${jar.jmx.impl.title}" />
<attribute name="Implementation-Version" value="${project.build.fulltag}" /> <attribute name="Implementation-Version" value="${project.build.fulltag}" />
<attribute name="Implementation-Vendor" value="${jar.jmx.impl.vendor}" /> <attribute name="Implementation-Vendor" value="${jar.jmx.impl.vendor}" />
</section> </section>
</manifest> </manifest>

View File

@ -141,7 +141,7 @@ public class LeaseManager {
} }
private final Runnable callback; 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 private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1, = Executors.newScheduledThreadPool(1,

View File

@ -128,7 +128,7 @@ public class LeaseRenewer {
}; };
private final Callable<Long> doRenew; private final Callable<Long> doRenew;
private ScheduledFuture future; private ScheduledFuture<?> future;
private boolean closed = false; private boolean closed = false;
private long nextRenewTime; private long nextRenewTime;

View File

@ -247,7 +247,7 @@ public class DefaultMBeanServerInterceptor
MBeanRegistrationException, MBeanException, MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException { NotCompliantMBeanException, InstanceNotFoundException {
Class theClass; Class<?> theClass;
if (className == null) { if (className == null) {
final RuntimeException wrapped = final RuntimeException wrapped =
@ -327,7 +327,7 @@ public class DefaultMBeanServerInterceptor
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
Class theClass = object.getClass(); Class<?> theClass = object.getClass();
Introspector.checkCompliance(theClass); Introspector.checkCompliance(theClass);
@ -808,9 +808,8 @@ public class DefaultMBeanServerInterceptor
// on each specific attribute // on each specific attribute
// //
allowedAttributes = new AttributeList(attributes.size()); allowedAttributes = new AttributeList(attributes.size());
for (Iterator i = attributes.iterator(); i.hasNext();) { for (Attribute attribute : attributes.asList()) {
try { try {
Attribute attribute = (Attribute) i.next();
checkMBeanPermission(mbeanServerName, classname, attribute.getName(), checkMBeanPermission(mbeanServerName, classname, attribute.getName(),
name, "setAttribute"); name, "setAttribute");
allowedAttributes.add(attribute); 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 { throws SecurityException {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {

View File

@ -136,14 +136,14 @@ final class ClassLoaderRepositorySupport
new Hashtable<ObjectName,ClassLoader>(10); new Hashtable<ObjectName,ClassLoader>(10);
// from javax.management.loading.DefaultLoaderRepository // from javax.management.loading.DefaultLoaderRepository
public final Class loadClass(String className) public final Class<?> loadClass(String className)
throws ClassNotFoundException { throws ClassNotFoundException {
return loadClass(loaders, className, null, null); return loadClass(loaders, className, null, null);
} }
// from javax.management.loading.DefaultLoaderRepository // from javax.management.loading.DefaultLoaderRepository
public final Class loadClassWithout(ClassLoader without, String className) public final Class<?> loadClassWithout(ClassLoader without, String className)
throws ClassNotFoundException { throws ClassNotFoundException {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(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 { throws ClassNotFoundException {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER, MBEANSERVER_LOGGER.logp(Level.FINER,
@ -187,10 +187,10 @@ final class ClassLoaderRepositorySupport
} }
private Class loadClass(final LoaderEntry list[], private Class<?> loadClass(final LoaderEntry list[],
final String className, final String className,
final ClassLoader without, final ClassLoader without,
final ClassLoader stop) final ClassLoader stop)
throws ClassNotFoundException { throws ClassNotFoundException {
final int size = list.length; final int size = list.length;
for(int i=0; i<size; i++) { for(int i=0; i<size; i++) {

View File

@ -68,12 +68,12 @@ final class ConvertingMethod {
return method.getName(); return method.getName();
} }
OpenType getOpenReturnType() { OpenType<?> getOpenReturnType() {
return returnMapping.getOpenType(); return returnMapping.getOpenType();
} }
OpenType[] getOpenParameterTypes() { OpenType<?>[] getOpenParameterTypes() {
final OpenType[] types = new OpenType[paramMappings.length]; final OpenType<?>[] types = new OpenType<?>[paramMappings.length];
for (int i = 0; i < paramMappings.length; i++) for (int i = 0; i < paramMappings.length; i++)
types[i] = paramMappings[i].getOpenType(); types[i] = paramMappings[i].getOpenType();
return types; return types;

View File

@ -26,7 +26,8 @@
package com.sun.jmx.mbeanserver; package com.sun.jmx.mbeanserver;
import static com.sun.jmx.mbeanserver.Util.*; 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 javax.management.openmbean.MXBeanMappingClass;
import static javax.management.openmbean.SimpleType.*; import static javax.management.openmbean.SimpleType.*;
@ -120,7 +121,7 @@ import javax.management.openmbean.TabularType;
*/ */
public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
static abstract class NonNullMXBeanMapping extends MXBeanMapping { static abstract class NonNullMXBeanMapping extends MXBeanMapping {
NonNullMXBeanMapping(Type javaType, OpenType openType) { NonNullMXBeanMapping(Type javaType, OpenType<?> openType) {
super(javaType, openType); super(javaType, openType);
} }
@ -195,15 +196,15 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
static { static {
/* Set up the mappings for Java types that map to SimpleType. */ /* Set up the mappings for Java types that map to SimpleType. */
final OpenType[] simpleTypes = { final OpenType<?>[] simpleTypes = {
BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE, BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE,
DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING, DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING,
VOID, VOID,
}; };
for (int i = 0; i < simpleTypes.length; i++) { for (int i = 0; i < simpleTypes.length; i++) {
final OpenType t = simpleTypes[i]; final OpenType<?> t = simpleTypes[i];
Class c; Class<?> c;
try { try {
c = Class.forName(t.getClassName(), false, c = Class.forName(t.getClassName(), false,
ObjectName.class.getClassLoader()); ObjectName.class.getClassLoader());
@ -224,7 +225,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
if (primitiveType != void.class) { if (primitiveType != void.class) {
final Class<?> primitiveArrayType = final Class<?> primitiveArrayType =
Array.newInstance(primitiveType, 0).getClass(); Array.newInstance(primitiveType, 0).getClass();
final OpenType primitiveArrayOpenType = final OpenType<?> primitiveArrayOpenType =
ArrayType.getPrimitiveArrayType(primitiveArrayType); ArrayType.getPrimitiveArrayType(primitiveArrayType);
final MXBeanMapping primitiveArrayMapping = final MXBeanMapping primitiveArrayMapping =
new IdentityMapping(primitiveArrayType, new IdentityMapping(primitiveArrayType,
@ -247,8 +248,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
public synchronized MXBeanMapping mappingForType(Type objType, public synchronized MXBeanMapping mappingForType(Type objType,
MXBeanMappingFactory factory) MXBeanMappingFactory factory)
throws OpenDataException { throws OpenDataException {
if (inProgress.containsKey(objType)) if (inProgress.containsKey(objType)) {
throw new OpenDataException("Recursive data structure"); throw new OpenDataException(
"Recursive data structure, including " + typeName(objType));
}
MXBeanMapping mapping; MXBeanMapping mapping;
@ -259,6 +262,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
inProgress.put(objType, objType); inProgress.put(objType, objType);
try { try {
mapping = makeMapping(objType, factory); mapping = makeMapping(objType, factory);
} catch (OpenDataException e) {
throw openDataException("Cannot convert type: " + typeName(objType), e);
} finally { } finally {
inProgress.remove(objType); inProgress.remove(objType);
} }
@ -285,13 +290,13 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
Type componentType = Type componentType =
((GenericArrayType) objType).getGenericComponentType(); ((GenericArrayType) objType).getGenericComponentType();
return makeArrayOrCollectionMapping(objType, componentType, factory); return makeArrayOrCollectionMapping(objType, componentType, factory);
} else if (objType instanceof Class) { } else if (objType instanceof Class<?>) {
Class<?> objClass = (Class<?>) objType; Class<?> objClass = (Class<?>) objType;
if (objClass.isEnum()) { if (objClass.isEnum()) {
// Huge hack to avoid compiler warnings here. The ElementType // Huge hack to avoid compiler warnings here. The ElementType
// parameter is ignored but allows us to obtain a type variable // parameter is ignored but allows us to obtain a type variable
// T that matches <T extends Enum<T>>. // T that matches <T extends Enum<T>>.
return makeEnumMapping((Class) objClass, ElementType.class); return makeEnumMapping((Class<?>) objClass, ElementType.class);
} else if (objClass.isArray()) { } else if (objClass.isArray()) {
Type componentType = objClass.getComponentType(); Type componentType = objClass.getComponentType();
return makeArrayOrCollectionMapping(objClass, componentType, return makeArrayOrCollectionMapping(objClass, componentType,
@ -354,7 +359,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
} }
private static <T extends Enum<T>> MXBeanMapping private static <T extends Enum<T>> MXBeanMapping
makeEnumMapping(Class enumClass, Class<T> fake) { makeEnumMapping(Class<?> enumClass, Class<T> fake) {
return new EnumMapping<T>(Util.<Class<T>>cast(enumClass)); return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));
} }
@ -411,17 +416,17 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
MXBeanMappingFactory factory) MXBeanMappingFactory factory)
throws OpenDataException { throws OpenDataException {
final String objTypeName = objType.toString(); final String objTypeName = typeName(objType);
final MXBeanMapping keyMapping = factory.mappingForType(keyType, factory); final MXBeanMapping keyMapping = factory.mappingForType(keyType, factory);
final MXBeanMapping valueMapping = factory.mappingForType(valueType, factory); final MXBeanMapping valueMapping = factory.mappingForType(valueType, factory);
final OpenType keyOpenType = keyMapping.getOpenType(); final OpenType<?> keyOpenType = keyMapping.getOpenType();
final OpenType valueOpenType = valueMapping.getOpenType(); final OpenType<?> valueOpenType = valueMapping.getOpenType();
final CompositeType rowType = final CompositeType rowType =
new CompositeType(objTypeName, new CompositeType(objTypeName,
objTypeName, objTypeName,
keyValueArray, keyValueArray,
keyValueArray, keyValueArray,
new OpenType[] {keyOpenType, valueOpenType}); new OpenType<?>[] {keyOpenType, valueOpenType});
final TabularType tabularType = final TabularType tabularType =
new TabularType(objTypeName, objTypeName, rowType, keyArray); new TabularType(objTypeName, objTypeName, rowType, keyArray);
return new TabularMapping(objType, sortedMap, tabularType, return new TabularMapping(objType, sortedMap, tabularType,
@ -440,8 +445,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Type rawType = objType.getRawType(); final Type rawType = objType.getRawType();
if (rawType instanceof Class) { if (rawType instanceof Class<?>) {
Class c = (Class<?>) rawType; Class<?> c = (Class<?>) rawType;
if (c == List.class || c == Set.class || c == SortedSet.class) { if (c == List.class || c == Set.class || c == SortedSet.class) {
Type[] actuals = objType.getActualTypeArguments(); Type[] actuals = objType.getActualTypeArguments();
assert(actuals.length == 1); assert(actuals.length == 1);
@ -468,7 +473,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
return new MXBeanRefMapping(t); return new MXBeanRefMapping(t);
} }
private MXBeanMapping makeCompositeMapping(Class c, private MXBeanMapping makeCompositeMapping(Class<?> c,
MXBeanMappingFactory factory) MXBeanMappingFactory factory)
throws OpenDataException { throws OpenDataException {
@ -514,7 +519,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Method[] getters = new Method[nitems]; final Method[] getters = new Method[nitems];
final String[] itemNames = new String[nitems]; final String[] itemNames = new String[nitems];
final OpenType[] openTypes = new OpenType[nitems]; final OpenType<?>[] openTypes = new OpenType<?>[nitems];
int i = 0; int i = 0;
for (Map.Entry<String,Method> entry : getterMap.entrySet()) { for (Map.Entry<String,Method> entry : getterMap.entrySet()) {
itemNames[i] = entry.getKey(); 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 can be directly represented by an ArrayType, and an int needs no mapping
because reflection takes care of it. */ because reflection takes care of it. */
private static final class IdentityMapping extends NonNullMXBeanMapping { private static final class IdentityMapping extends NonNullMXBeanMapping {
IdentityMapping(Type targetType, OpenType openType) { IdentityMapping(Type targetType, OpenType<?> openType) {
super(targetType, openType); super(targetType, openType);
} }
@ -576,7 +581,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
@Override @Override
final Object toNonNullOpenValue(Object value) { final Object toNonNullOpenValue(Object value) {
return ((Enum) value).name(); return ((Enum<?>) value).name();
} }
@Override @Override
@ -595,7 +600,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class ArrayMapping extends NonNullMXBeanMapping { private static final class ArrayMapping extends NonNullMXBeanMapping {
ArrayMapping(Type targetType, ArrayMapping(Type targetType,
ArrayType openArrayType, Class openArrayClass, ArrayType<?> openArrayType, Class<?> openArrayClass,
MXBeanMapping elementMapping) { MXBeanMapping elementMapping) {
super(targetType, openArrayType); super(targetType, openArrayType);
this.elementMapping = elementMapping; this.elementMapping = elementMapping;
@ -623,7 +628,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
if (javaType instanceof GenericArrayType) { if (javaType instanceof GenericArrayType) {
componentType = componentType =
((GenericArrayType) javaType).getGenericComponentType(); ((GenericArrayType) javaType).getGenericComponentType();
} else if (javaType instanceof Class && } else if (javaType instanceof Class<?> &&
((Class<?>) javaType).isArray()) { ((Class<?>) javaType).isArray()) {
componentType = ((Class<?>) javaType).getComponentType(); componentType = ((Class<?>) javaType).getComponentType();
} else { } else {
@ -651,8 +656,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class CollectionMapping extends NonNullMXBeanMapping { private static final class CollectionMapping extends NonNullMXBeanMapping {
CollectionMapping(Type targetType, CollectionMapping(Type targetType,
ArrayType openArrayType, ArrayType<?> openArrayType,
Class openArrayClass, Class<?> openArrayClass,
MXBeanMapping elementMapping) { MXBeanMapping elementMapping) {
super(targetType, openArrayType); super(targetType, openArrayType);
this.elementMapping = elementMapping; this.elementMapping = elementMapping;
@ -662,26 +667,28 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
and all Sets to TreeSet. (TreeSet because it is a SortedSet, and all Sets to TreeSet. (TreeSet because it is a SortedSet,
so works for both Set and SortedSet.) */ so works for both Set and SortedSet.) */
Type raw = ((ParameterizedType) targetType).getRawType(); Type raw = ((ParameterizedType) targetType).getRawType();
Class c = (Class<?>) raw; Class<?> c = (Class<?>) raw;
final Class<?> collC;
if (c == List.class) if (c == List.class)
collectionClass = ArrayList.class; collC = ArrayList.class;
else if (c == Set.class) else if (c == Set.class)
collectionClass = HashSet.class; collC = HashSet.class;
else if (c == SortedSet.class) else if (c == SortedSet.class)
collectionClass = TreeSet.class; collC = TreeSet.class;
else { // can't happen else { // can't happen
assert(false); assert(false);
collectionClass = null; collC = null;
} }
collectionClass = Util.cast(collC);
} }
@Override @Override
final Object toNonNullOpenValue(Object value) final Object toNonNullOpenValue(Object value)
throws OpenDataException { throws OpenDataException {
final Collection valueCollection = (Collection) value; final Collection<?> valueCollection = (Collection<?>) value;
if (valueCollection instanceof SortedSet) { if (valueCollection instanceof SortedSet<?>) {
Comparator comparator = Comparator<?> comparator =
((SortedSet) valueCollection).comparator(); ((SortedSet<?>) valueCollection).comparator();
if (comparator != null) { if (comparator != null) {
final String msg = final String msg =
"Cannot convert SortedSet with non-null comparator: " + "Cannot convert SortedSet with non-null comparator: " +
@ -725,7 +732,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
elementMapping.checkReconstructible(); elementMapping.checkReconstructible();
} }
private final Class<? extends Collection> collectionClass; private final Class<? extends Collection<?>> collectionClass;
private final MXBeanMapping elementMapping; private final MXBeanMapping elementMapping;
} }
@ -794,8 +801,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
@Override @Override
final Object toNonNullOpenValue(Object value) throws OpenDataException { final Object toNonNullOpenValue(Object value) throws OpenDataException {
final Map<Object, Object> valueMap = cast(value); final Map<Object, Object> valueMap = cast(value);
if (valueMap instanceof SortedMap) { if (valueMap instanceof SortedMap<?,?>) {
Comparator comparator = ((SortedMap) valueMap).comparator(); Comparator<?> comparator = ((SortedMap<?,?>) valueMap).comparator();
if (comparator != null) { if (comparator != null) {
final String msg = final String msg =
"Cannot convert SortedMap with non-null comparator: " + "Cannot convert SortedMap with non-null comparator: " +
@ -806,7 +813,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final TabularType tabularType = (TabularType) getOpenType(); final TabularType tabularType = (TabularType) getOpenType();
final TabularData table = new TabularDataSupport(tabularType); final TabularData table = new TabularDataSupport(tabularType);
final CompositeType rowType = tabularType.getRowType(); final CompositeType rowType = tabularType.getRowType();
for (Map.Entry entry : valueMap.entrySet()) { for (Map.Entry<Object, Object> entry : valueMap.entrySet()) {
final Object openKey = keyMapping.toOpenValue(entry.getKey()); final Object openKey = keyMapping.toOpenValue(entry.getKey());
final Object openValue = valueMapping.toOpenValue(entry.getValue()); final Object openValue = valueMapping.toOpenValue(entry.getValue());
final CompositeData row; final CompositeData row;
@ -852,7 +859,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
} }
private final class CompositeMapping extends NonNullMXBeanMapping { private final class CompositeMapping extends NonNullMXBeanMapping {
CompositeMapping(Class targetClass, CompositeMapping(Class<?> targetClass,
CompositeType compositeType, CompositeType compositeType,
String[] itemNames, String[] itemNames,
Method[] getters, Method[] getters,
@ -901,7 +908,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
if (compositeBuilder != null) if (compositeBuilder != null)
return; return;
Class targetClass = (Class<?>) getJavaType(); Class<?> targetClass = (Class<?>) getJavaType();
/* In this 2D array, each subarray is a set of builders where /* In this 2D array, each subarray is a set of builders where
there is no point in consulting the ones after the first if there is no point in consulting the ones after the first if
the first refuses. */ the first refuses. */
@ -924,6 +931,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
concatenating each Builder's explanation of why it concatenating each Builder's explanation of why it
isn't applicable. */ isn't applicable. */
final StringBuilder whyNots = new StringBuilder(); final StringBuilder whyNots = new StringBuilder();
Throwable possibleCause = null;
find: find:
for (CompositeBuilder[] relatedBuilders : builders) { for (CompositeBuilder[] relatedBuilders : builders) {
for (int i = 0; i < relatedBuilders.length; i++) { for (int i = 0; i < relatedBuilders.length; i++) {
@ -933,6 +941,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
foundBuilder = builder; foundBuilder = builder;
break find; break find;
} }
Throwable cause = builder.possibleCause();
if (cause != null)
possibleCause = cause;
if (whyNot.length() > 0) { if (whyNot.length() > 0) {
if (whyNots.length() > 0) if (whyNots.length() > 0)
whyNots.append("; "); whyNots.append("; ");
@ -943,10 +954,12 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
} }
} }
if (foundBuilder == null) { if (foundBuilder == null) {
final String msg = String msg =
"Do not know how to make a " + targetClass.getName() + "Do not know how to make a " + targetClass.getName() +
" from a CompositeData: " + whyNots; " from a CompositeData: " + whyNots;
throw new InvalidObjectException(msg); if (possibleCause != null)
msg += ". Remaining exceptions show a POSSIBLE cause.";
throw invalidObjectException(msg, possibleCause);
} }
compositeBuilder = foundBuilder; compositeBuilder = foundBuilder;
} }
@ -973,7 +986,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
/** Converts from a CompositeData to an instance of the targetClass. */ /** Converts from a CompositeData to an instance of the targetClass. */
private static abstract class CompositeBuilder { private static abstract class CompositeBuilder {
CompositeBuilder(Class targetClass, String[] itemNames) { CompositeBuilder(Class<?> targetClass, String[] itemNames) {
this.targetClass = targetClass; this.targetClass = targetClass;
this.itemNames = itemNames; this.itemNames = itemNames;
} }
@ -994,6 +1007,16 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
abstract String applicable(Method[] getters) abstract String applicable(Method[] getters)
throws InvalidObjectException; 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, abstract Object fromCompositeData(CompositeData cd,
String[] itemNames, String[] itemNames,
MXBeanMapping[] converters) MXBeanMapping[] converters)
@ -1008,7 +1031,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class CompositeBuilderViaFrom private static final class CompositeBuilderViaFrom
extends CompositeBuilder { extends CompositeBuilder {
CompositeBuilderViaFrom(Class targetClass, String[] itemNames) { CompositeBuilderViaFrom(Class<?> targetClass, String[] itemNames) {
super(targetClass, itemNames); super(targetClass, itemNames);
} }
@ -1018,8 +1041,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
Class<?> targetClass = getTargetClass(); Class<?> targetClass = getTargetClass();
try { try {
Method fromMethod = Method fromMethod =
targetClass.getMethod("from", targetClass.getMethod("from", CompositeData.class);
new Class[] {CompositeData.class});
if (!Modifier.isStatic(fromMethod.getModifiers())) { if (!Modifier.isStatic(fromMethod.getModifiers())) {
final String msg = final String msg =
@ -1030,8 +1052,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
if (fromMethod.getReturnType() != getTargetClass()) { if (fromMethod.getReturnType() != getTargetClass()) {
final String msg = final String msg =
"Method from(CompositeData) returns " + "Method from(CompositeData) returns " +
fromMethod.getReturnType().getName() + typeName(fromMethod.getReturnType()) +
" not " + targetClass.getName(); " not " + typeName(targetClass);
throw new InvalidObjectException(msg); 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 If all the getters are OK, then the "applicable" method will return
an empty string and the other builders will be tried. */ an empty string and the other builders will be tried. */
private static class CompositeBuilderCheckGetters extends CompositeBuilder { private static class CompositeBuilderCheckGetters extends CompositeBuilder {
CompositeBuilderCheckGetters(Class targetClass, String[] itemNames, CompositeBuilderCheckGetters(Class<?> targetClass, String[] itemNames,
MXBeanMapping[] getterConverters) { MXBeanMapping[] getterConverters) {
super(targetClass, itemNames); super(targetClass, itemNames);
this.getterConverters = getterConverters; this.getterConverters = getterConverters;
@ -1082,6 +1104,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
try { try {
getterConverters[i].checkReconstructible(); getterConverters[i].checkReconstructible();
} catch (InvalidObjectException e) { } catch (InvalidObjectException e) {
possibleCause = e;
return "method " + getters[i].getName() + " returns type " + return "method " + getters[i].getName() + " returns type " +
"that cannot be mapped back from OpenData"; "that cannot be mapped back from OpenData";
} }
@ -1089,6 +1112,11 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
return ""; return "";
} }
@Override
Throwable possibleCause() {
return possibleCause;
}
final Object fromCompositeData(CompositeData cd, final Object fromCompositeData(CompositeData cd,
String[] itemNames, String[] itemNames,
MXBeanMapping[] converters) { MXBeanMapping[] converters) {
@ -1096,6 +1124,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
} }
private final MXBeanMapping[] getterConverters; private final MXBeanMapping[] getterConverters;
private Throwable possibleCause;
} }
/** Builder for when the target class has a setter for every getter. */ /** 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]; Method[] setters = new Method[getters.length];
for (int i = 0; i < getters.length; i++) { for (int i = 0; i < getters.length; i++) {
Method getter = getters[i]; Method getter = getters[i];
Class returnType = getter.getReturnType(); Class<?> returnType = getter.getReturnType();
String name = propertyName(getter); String name = propertyName(getter);
String setterName = "set" + name; String setterName = "set" + name;
Method setter; Method setter;
@ -1163,7 +1192,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class CompositeBuilderViaConstructor private static final class CompositeBuilderViaConstructor
extends CompositeBuilder { extends CompositeBuilder {
CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) { CompositeBuilderViaConstructor(Class<?> targetClass, String[] itemNames) {
super(targetClass, itemNames); super(targetClass, itemNames);
} }
@ -1171,7 +1200,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class; final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class;
Class targetClass = getTargetClass(); Class<?> targetClass = getTargetClass();
Constructor<?>[] constrs = targetClass.getConstructors(); Constructor<?>[] constrs = targetClass.getConstructors();
// Applicable if and only if there are any annotated constructors // 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++) { for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i]; String propertyName = propertyNames[i];
if (!getterMap.containsKey(propertyName)) { if (!getterMap.containsKey(propertyName)) {
final String msg = String msg =
"@ConstructorProperties includes name " + propertyName + "@ConstructorProperties includes name " + propertyName +
" which does not correspond to a property: " + " which does not correspond to a property";
constr; for (String getterName : getterMap.keySet()) {
if (getterName.equalsIgnoreCase(propertyName)) {
msg += " (differs only in case from property " +
getterName + ")";
}
}
msg += ": " + constr;
throw new InvalidObjectException(msg); throw new InvalidObjectException(msg);
} }
int getterIndex = getterMap.get(propertyName); int getterIndex = getterMap.get(propertyName);
@ -1384,12 +1419,12 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class CompositeBuilderViaProxy private static final class CompositeBuilderViaProxy
extends CompositeBuilder { extends CompositeBuilder {
CompositeBuilderViaProxy(Class targetClass, String[] itemNames) { CompositeBuilderViaProxy(Class<?> targetClass, String[] itemNames) {
super(targetClass, itemNames); super(targetClass, itemNames);
} }
String applicable(Method[] getters) { String applicable(Method[] getters) {
Class targetClass = getTargetClass(); Class<?> targetClass = getTargetClass();
if (!targetClass.isInterface()) if (!targetClass.isInterface())
return "not an interface"; return "not an interface";
Set<Method> methods = Set<Method> methods =
@ -1401,7 +1436,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
String bad = null; String bad = null;
for (Method m : methods) { for (Method m : methods) {
String mname = m.getName(); String mname = m.getName();
Class[] mparams = m.getParameterTypes(); Class<?>[] mparams = m.getParameterTypes();
try { try {
Method om = Object.class.getMethod(mname, mparams); Method om = Object.class.getMethod(mname, mparams);
if (!Modifier.isPublic(om.getModifiers())) if (!Modifier.isPublic(om.getModifiers()))
@ -1422,10 +1457,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Object fromCompositeData(CompositeData cd, final Object fromCompositeData(CompositeData cd,
String[] itemNames, String[] itemNames,
MXBeanMapping[] converters) { MXBeanMapping[] converters) {
final Class targetClass = getTargetClass(); final Class<?> targetClass = getTargetClass();
return return
Proxy.newProxyInstance(targetClass.getClassLoader(), Proxy.newProxyInstance(targetClass.getClassLoader(),
new Class[] {targetClass}, new Class<?>[] {targetClass},
new CompositeDataInvocationHandler(cd)); new CompositeDataInvocationHandler(cd));
} }
} }
@ -1447,9 +1482,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
return openDataException(cause.getMessage(), cause); return openDataException(cause.getMessage(), cause);
} }
static void mustBeComparable(Class collection, Type element) static void mustBeComparable(Class<?> collection, Type element)
throws OpenDataException { throws OpenDataException {
if (!(element instanceof Class) if (!(element instanceof Class<?>)
|| !Comparable.class.isAssignableFrom((Class<?>) element)) { || !Comparable.class.isAssignableFrom((Class<?>) element)) {
final String msg = final String msg =
"Parameter class " + element + " of " + "Parameter class " + element + " of " +

View File

@ -115,7 +115,7 @@ public class Introspector {
* Dynamic MBeans, <code>false</code> otherwise. * Dynamic MBeans, <code>false</code> 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 // Check if the MBean implements the DynamicMBean interface
return javax.management.DynamicMBean.class.isAssignableFrom(c); return javax.management.DynamicMBean.class.isAssignableFrom(c);
} }
@ -134,7 +134,7 @@ public class Introspector {
* MBeanServer. * MBeanServer.
* *
**/ **/
public static void testCreation(Class c) public static void testCreation(Class<?> c)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
// Check if the class is a concrete class // Check if the class is a concrete class
final int mods = c.getModifiers(); final int mods = c.getModifiers();
@ -143,7 +143,7 @@ public class Introspector {
} }
// Check if the MBean has a public constructor // Check if the MBean has a public constructor
final Constructor[] consList = c.getConstructors(); final Constructor<?>[] consList = c.getConstructors();
if (consList.length == 0) { if (consList.length == 0) {
throw new NotCompliantMBeanException("MBean class must have public constructor"); throw new NotCompliantMBeanException("MBean class must have public constructor");
} }
@ -253,7 +253,7 @@ public class Introspector {
* @exception NotCompliantMBeanException The specified class is not a * @exception NotCompliantMBeanException The specified class is not a
* JMX compliant MBean * JMX compliant MBean
*/ */
public static MBeanInfo testCompliance(Class baseClass) public static MBeanInfo testCompliance(Class<?> baseClass)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
// ------------------------------ // ------------------------------
@ -267,7 +267,7 @@ public class Introspector {
return testCompliance(baseClass, null); return testCompliance(baseClass, null);
} }
public static void testComplianceMXBeanInterface(Class interfaceClass, public static void testComplianceMXBeanInterface(Class<?> interfaceClass,
MXBeanMappingFactory factory) MXBeanMappingFactory factory)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass); MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass);
@ -596,10 +596,10 @@ public class Introspector {
ss[i] = (String) annotationToField(xx[i]); ss[i] = (String) annotationToField(xx[i]);
return ss; return ss;
} }
if (x instanceof Class) if (x instanceof Class<?>)
return ((Class<?>) x).getName(); return ((Class<?>) x).getName();
if (x instanceof Enum) if (x instanceof Enum<?>)
return ((Enum) x).name(); return ((Enum<?>) x).name();
// The only other possibility is that the value is another // The only other possibility is that the value is another
// annotation, or that the language has evolved since this code // annotation, or that the language has evolved since this code
// was written. We don't allow for either of those currently. // was written. We don't allow for either of those currently.

View File

@ -33,6 +33,7 @@ import java.security.AccessController;
import java.security.Permission; import java.security.Permission;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
@ -1144,7 +1145,7 @@ public final class JmxMBeanServer
// This call requires MBeanPermission 'getClassLoaderRepository' // This call requires MBeanPermission 'getClassLoaderRepository'
final ClassLoaderRepository clr = getClassLoaderRepository(); final ClassLoaderRepository clr = getClassLoaderRepository();
Class theClass; Class<?> theClass;
try { try {
if (clr == null) throw new ClassNotFoundException(className); if (clr == null) throw new ClassNotFoundException(className);
theClass = clr.loadClass(className); theClass = clr.loadClass(className);
@ -1457,23 +1458,22 @@ public final class JmxMBeanServer
*/ */
private AttributeList cloneAttributeList(AttributeList list) { private AttributeList cloneAttributeList(AttributeList list) {
if (list != null) { if (list != null) {
List<Attribute> alist = list.asList();
if (!list.getClass().equals(AttributeList.class)) { if (!list.getClass().equals(AttributeList.class)) {
// Create new attribute list // Create new attribute list
// //
AttributeList newList = new AttributeList(list.size()); AttributeList newList = new AttributeList(alist.size());
// Iterate through list and replace non JMX attributes // Iterate through list and replace non JMX attributes
// //
for (Iterator i = list.iterator(); i.hasNext(); ) { for (Attribute attribute : alist)
Attribute attribute = (Attribute) i.next();
newList.add(cloneAttribute(attribute)); newList.add(cloneAttribute(attribute));
}
return newList; return newList;
} else { } else {
// Iterate through list and replace non JMX attributes // Iterate through list and replace non JMX attributes
// //
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < alist.size(); i++) {
Attribute attribute = (Attribute) list.get(i); Attribute attribute = alist.get(i);
if (!attribute.getClass().equals(Attribute.class)) { if (!attribute.getClass().equals(Attribute.class)) {
list.set(i, cloneAttribute(attribute)); list.set(i, cloneAttribute(attribute));
} }

View File

@ -70,7 +70,7 @@ public class MBeanInstantiator {
* instantiate an MBean of this class in the MBeanServer. * instantiate an MBean of this class in the MBeanServer.
* e.g. it must have a public constructor, be a concrete class... * 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); Introspector.testCreation(c);
} }
@ -78,10 +78,10 @@ public class MBeanInstantiator {
* Loads the class with the specified name using this object's * Loads the class with the specified name using this object's
* Default Loader Repository. * Default Loader Repository.
**/ **/
public Class findClassWithDefaultLoaderRepository(String className) public Class<?> findClassWithDefaultLoaderRepository(String className)
throws ReflectionException { throws ReflectionException {
Class theClass; Class<?> theClass;
if (className == null) { if (className == null) {
throw new RuntimeOperationsException(new throw new RuntimeOperationsException(new
IllegalArgumentException("The class name cannot be null"), 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 * Gets the class for the specified class name using the MBean
* Interceptor's classloader * Interceptor's classloader
*/ */
public Class findClass(String className, ClassLoader loader) public Class<?> findClass(String className, ClassLoader loader)
throws ReflectionException { throws ReflectionException {
return loadClass(className,loader); return loadClass(className,loader);
@ -115,7 +115,7 @@ public class MBeanInstantiator {
* Gets the class for the specified class name using the specified * Gets the class for the specified class name using the specified
* class loader * class loader
*/ */
public Class findClass(String className, ObjectName aLoader) public Class<?> findClass(String className, ObjectName aLoader)
throws ReflectionException, InstanceNotFoundException { throws ReflectionException, InstanceNotFoundException {
if (aLoader == null) if (aLoader == null)
@ -140,14 +140,14 @@ public class MBeanInstantiator {
* Return an array of Class corresponding to the given signature, using * Return an array of Class corresponding to the given signature, using
* the specified class loader. * the specified class loader.
*/ */
public Class[] findSignatureClasses(String signature[], public Class<?>[] findSignatureClasses(String signature[],
ClassLoader loader) ClassLoader loader)
throws ReflectionException { throws ReflectionException {
if (signature == null) return null; if (signature == null) return null;
final ClassLoader aLoader = loader; final ClassLoader aLoader = loader;
final int length= signature.length; final int length= signature.length;
final Class tab[]=new Class[length]; final Class<?> tab[]=new Class<?>[length];
if (length == 0) return tab; if (length == 0) return tab;
try { try {
@ -156,7 +156,7 @@ public class MBeanInstantiator {
// forth) // forth)
// //
final Class primCla = primitiveClasses.get(signature[i]); final Class<?> primCla = primitiveClasses.get(signature[i]);
if (primCla != null) { if (primCla != null) {
tab[i] = primCla; tab[i] = primCla;
continue; continue;
@ -203,14 +203,14 @@ public class MBeanInstantiator {
* Instantiates an object given its class, using its empty constructor. * Instantiates an object given its class, using its empty constructor.
* The call returns a reference to the newly created object. * The call returns a reference to the newly created object.
*/ */
public Object instantiate(Class theClass) public Object instantiate(Class<?> theClass)
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
Object moi; Object moi;
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
Constructor cons = findConstructor(theClass, null); Constructor<?> cons = findConstructor(theClass, null);
if (cons == null) { if (cons == null) {
throw new ReflectionException(new throw new ReflectionException(new
NoSuchMethodException("No such constructor")); NoSuchMethodException("No such constructor"));
@ -257,14 +257,14 @@ public class MBeanInstantiator {
* signature of its constructor The call returns a reference to * signature of its constructor The call returns a reference to
* the newly created object. * the newly created object.
*/ */
public Object instantiate(Class theClass, Object params[], public Object instantiate(Class<?> theClass, Object params[],
String signature[], ClassLoader loader) String signature[], ClassLoader loader)
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
// Instantiate the new object // Instantiate the new object
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
final Class[] tab; final Class<?>[] tab;
Object moi; Object moi;
try { try {
// Build the signature of the method // Build the signature of the method
@ -283,7 +283,7 @@ public class MBeanInstantiator {
} }
// Query the metadata service to get the right constructor // Query the metadata service to get the right constructor
Constructor cons = findConstructor(theClass, tab); Constructor<?> cons = findConstructor(theClass, tab);
if (cons == null) { if (cons == null) {
throw new ReflectionException(new throw new ReflectionException(new
@ -407,7 +407,7 @@ public class MBeanInstantiator {
throw new RuntimeOperationsException(new throw new RuntimeOperationsException(new
IllegalArgumentException(), "Null className passed in parameter"); IllegalArgumentException(), "Null className passed in parameter");
} }
Class theClass; Class<?> theClass;
if (loaderName == null) { if (loaderName == null) {
// Load the class using the agent class loader // Load the class using the agent class loader
theClass = findClass(className, loader); theClass = findClass(className, loader);
@ -547,7 +547,7 @@ public class MBeanInstantiator {
throws ReflectionException, throws ReflectionException,
MBeanException { MBeanException {
Class theClass = findClassWithDefaultLoaderRepository(className); Class<?> theClass = findClassWithDefaultLoaderRepository(className);
return instantiate(theClass, params, signature, loader); return instantiate(theClass, params, signature, loader);
} }
@ -595,7 +595,7 @@ public class MBeanInstantiator {
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
Class theClass; Class<?> theClass;
if (loaderName == null) { if (loaderName == null) {
theClass = findClass(className, loader); theClass = findClass(className, loader);
@ -617,10 +617,10 @@ public class MBeanInstantiator {
* Load a class with the specified loader, or with this object * Load a class with the specified loader, or with this object
* class loader if the specified loader is null. * class loader if the specified loader is null.
**/ **/
static Class loadClass(String className, ClassLoader loader) static Class<?> loadClass(String className, ClassLoader loader)
throws ReflectionException { throws ReflectionException {
Class theClass; Class<?> theClass;
if (className == null) { if (className == null) {
throw new RuntimeOperationsException(new throw new RuntimeOperationsException(new
IllegalArgumentException("The class name cannot be null"), 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, * Load the classes specified in the signature with the given loader,
* or with this object class loader. * or with this object class loader.
**/ **/
static Class[] loadSignatureClasses(String signature[], static Class<?>[] loadSignatureClasses(String signature[],
ClassLoader loader) ClassLoader loader)
throws ReflectionException { throws ReflectionException {
if (signature == null) return null; if (signature == null) return null;
final ClassLoader aLoader = final ClassLoader aLoader =
(loader==null?MBeanInstantiator.class.getClassLoader():loader); (loader==null?MBeanInstantiator.class.getClassLoader():loader);
final int length= signature.length; final int length= signature.length;
final Class tab[]=new Class[length]; final Class<?> tab[]=new Class<?>[length];
if (length == 0) return tab; if (length == 0) return tab;
try { try {
@ -664,7 +664,7 @@ public class MBeanInstantiator {
// forth) // forth)
// //
final Class primCla = primitiveClasses.get(signature[i]); final Class<?> primCla = primitiveClasses.get(signature[i]);
if (primCla != null) { if (primCla != null) {
tab[i] = primCla; tab[i] = primCla;
continue; continue;
@ -710,9 +710,9 @@ public class MBeanInstantiator {
private static final Map<String, Class<?>> primitiveClasses = Util.newMap(); private static final Map<String, Class<?>> primitiveClasses = Util.newMap();
static { static {
for (Class<?> c : new Class[] {byte.class, short.class, int.class, for (Class<?> c : new Class<?>[] {byte.class, short.class, int.class,
long.class, float.class, double.class, long.class, float.class, double.class,
char.class, boolean.class}) char.class, boolean.class})
primitiveClasses.put(c.getName(), c); primitiveClasses.put(c.getName(), c);
} }
} }

Some files were not shown because too many files have changed in this diff Show More