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
744554f5a3290e11c71cd2ddb1aff49e431f9ed0 jdk7-b37
cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38
ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39

View File

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

View File

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

View File

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

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

View File

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

View File

@ -906,7 +906,7 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
// load next super to check
if (UseCompressedOops) {
ld( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3);
lduw( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3);
// Bump array pointer forward one oop
add( Rtmp2, 4, Rtmp2 );
} else {

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

View File

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

View File

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

View File

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

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 {
Compile* C = ra_->C;
if( C->in_24_bit_fp_mode() ) {
tty->print("FLDCW 24 bit fpu control word");
tty->print_cr(""); tty->print("\t");
st->print("FLDCW 24 bit fpu control word");
st->print_cr(""); st->print("\t");
}
int framesize = C->frame_slots() << LogBytesPerInt;
@ -510,22 +510,22 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
// stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(framesize)) {
tty->print_cr("# stack bang"); tty->print("\t");
st->print_cr("# stack bang"); st->print("\t");
}
tty->print_cr("PUSHL EBP"); tty->print("\t");
st->print_cr("PUSHL EBP"); st->print("\t");
if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth
tty->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check");
tty->print_cr(""); tty->print("\t");
st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check");
st->print_cr(""); st->print("\t");
framesize -= wordSize;
}
if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) {
if (framesize) {
tty->print("SUB ESP,%d\t# Create frame",framesize);
st->print("SUB ESP,%d\t# Create frame",framesize);
}
} else {
tty->print("SUB ESP,%d\t# Create frame",framesize);
st->print("SUB ESP,%d\t# Create frame",framesize);
}
}
#endif
@ -725,18 +725,19 @@ static enum RC rc_class( OptoReg::Name reg ) {
return rc_xmm;
}
static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size ) {
static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg,
int opcode, const char *op_str, int size, outputStream* st ) {
if( cbuf ) {
emit_opcode (*cbuf, opcode );
encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false);
#ifndef PRODUCT
} else if( !do_size ) {
if( size != 0 ) tty->print("\n\t");
if( size != 0 ) st->print("\n\t");
if( opcode == 0x8B || opcode == 0x89 ) { // MOV
if( is_load ) tty->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset);
else tty->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]);
if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset);
else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]);
} else { // FLD, FST, PUSH, POP
tty->print("%s [ESP + #%d]",op_str,offset);
st->print("%s [ESP + #%d]",op_str,offset);
}
#endif
}
@ -746,7 +747,7 @@ static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset
// Helper for XMM registers. Extra opcode bits, limited syntax.
static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
int offset, int reg_lo, int reg_hi, int size ) {
int offset, int reg_lo, int reg_hi, int size, outputStream* st ) {
if( cbuf ) {
if( reg_lo+1 == reg_hi ) { // double move?
if( is_load && !UseXmmLoadAndClearUpper )
@ -764,17 +765,17 @@ static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false);
#ifndef PRODUCT
} else if( !do_size ) {
if( size != 0 ) tty->print("\n\t");
if( size != 0 ) st->print("\n\t");
if( reg_lo+1 == reg_hi ) { // double move?
if( is_load ) tty->print("%s %s,[ESP + #%d]",
if( is_load ) st->print("%s %s,[ESP + #%d]",
UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD",
Matcher::regName[reg_lo], offset);
else tty->print("MOVSD [ESP + #%d],%s",
else st->print("MOVSD [ESP + #%d],%s",
offset, Matcher::regName[reg_lo]);
} else {
if( is_load ) tty->print("MOVSS %s,[ESP + #%d]",
if( is_load ) st->print("MOVSS %s,[ESP + #%d]",
Matcher::regName[reg_lo], offset);
else tty->print("MOVSS [ESP + #%d],%s",
else st->print("MOVSS [ESP + #%d],%s",
offset, Matcher::regName[reg_lo]);
}
#endif
@ -785,7 +786,7 @@ static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
int src_hi, int dst_hi, int size ) {
int src_hi, int dst_hi, int size, outputStream* st ) {
if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers
if( cbuf ) {
if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) {
@ -796,11 +797,11 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst
emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] );
#ifndef PRODUCT
} else if( !do_size ) {
if( size != 0 ) tty->print("\n\t");
if( size != 0 ) st->print("\n\t");
if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move?
tty->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
} else {
tty->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
}
#endif
}
@ -813,11 +814,11 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst
emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] );
#ifndef PRODUCT
} else if( !do_size ) {
if( size != 0 ) tty->print("\n\t");
if( size != 0 ) st->print("\n\t");
if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move?
tty->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
} else {
tty->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
}
#endif
}
@ -825,28 +826,29 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst
}
}
static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size ) {
static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) {
if( cbuf ) {
emit_opcode(*cbuf, 0x8B );
emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] );
#ifndef PRODUCT
} else if( !do_size ) {
if( size != 0 ) tty->print("\n\t");
tty->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]);
if( size != 0 ) st->print("\n\t");
st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]);
#endif
}
return size+2;
}
static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, int offset, int size ) {
static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi,
int offset, int size, outputStream* st ) {
if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there
if( cbuf ) {
emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it)
emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] );
#ifndef PRODUCT
} else if( !do_size ) {
if( size != 0 ) tty->print("\n\t");
tty->print("FLD %s",Matcher::regName[src_lo]);
if( size != 0 ) st->print("\n\t");
st->print("FLD %s",Matcher::regName[src_lo]);
#endif
}
size += 2;
@ -864,7 +866,7 @@ static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int
assert( !OptoReg::is_valid(src_hi) && !OptoReg::is_valid(dst_hi), "no non-adjacent float-stores" );
}
return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size);
return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size, st);
}
uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const {
@ -892,16 +894,16 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
if( src_second == dst_first ) { // overlapping stack copy ranges
assert( src_second_rc == rc_stack && dst_second_rc == rc_stack, "we only expect a stk-stk copy here" );
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size);
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st);
src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits
}
// move low bits
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size);
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size, st);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size, st);
if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { // mov second bits
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size);
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st);
}
return size;
}
@ -909,15 +911,15 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
// --------------------------------------
// Check for integer reg-reg copy
if( src_first_rc == rc_int && dst_first_rc == rc_int )
size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size);
size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size, st);
// Check for integer store
if( src_first_rc == rc_int && dst_first_rc == rc_stack )
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size);
size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size, st);
// Check for integer load
if( dst_first_rc == rc_int && src_first_rc == rc_stack )
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size);
size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size, st);
// --------------------------------------
// Check for float reg-reg copy
@ -951,7 +953,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
// Check for float store
if( src_first_rc == rc_float && dst_first_rc == rc_stack ) {
return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size);
return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size, st);
}
// Check for float load
@ -987,17 +989,17 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) ||
(src_first+1 == src_second && dst_first+1 == dst_second),
"no non-adjacent float-moves" );
return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size);
return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size, st);
}
// Check for xmm store
if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) {
return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size);
return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size, st);
}
// Check for float xmm load
if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) {
return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size);
return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size, st);
}
// Copy from float reg to xmm reg
@ -1017,10 +1019,10 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
}
size += 4;
size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size);
size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size, st);
// Copy from the temp memory to the xmm reg.
size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size);
size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size, st);
if( cbuf ) {
emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8]
@ -1047,15 +1049,15 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
// Check for second word int-int move
if( src_second_rc == rc_int && dst_second_rc == rc_int )
return impl_mov_helper(cbuf,do_size,src_second,dst_second,size);
return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st);
// Check for second word integer store
if( src_second_rc == rc_int && dst_second_rc == rc_stack )
return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size);
return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st);
// Check for second word integer load
if( dst_second_rc == rc_int && src_second_rc == rc_stack )
return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size);
return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st);
Unimplemented();
@ -1318,7 +1320,11 @@ const uint Matcher::vector_ideal_reg(void) {
//
// NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0.
bool Matcher::is_short_branch_offset(int offset) {
bool Matcher::is_short_branch_offset(int rule, int offset) {
// the short version of jmpConUCF2 contains multiple branches,
// making the reach slightly less
if (rule == jmpConUCF2_rule)
return (-126 <= offset && offset <= 125);
return (-128 <= offset && offset <= 127);
}
@ -3307,7 +3313,7 @@ encode %{
// Beware -- there's a subtle invariant that fetch of the markword
// at [FETCH], below, will never observe a biased encoding (*101b).
// If this invariant is not held we risk exclusion (safety) failure.
if (UseBiasedLocking) {
if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters);
}
@ -3528,7 +3534,7 @@ encode %{
// Critically, the biased locking test must have precedence over
// and appear before the (box->dhw == 0) recursive stack-lock test.
if (UseBiasedLocking) {
if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
}
@ -5272,6 +5278,15 @@ operand eFlagsRegU() %{
interface(REG_INTER);
%}
operand eFlagsRegUCF() %{
constraint(ALLOC_IN_RC(int_flags));
match(RegFlags);
predicate(false);
format %{ "EFLAGS_U_CF" %}
interface(REG_INTER);
%}
// Condition Code Register used by long compare
operand flagsReg_long_LTGE() %{
constraint(ALLOC_IN_RC(int_flags));
@ -5749,12 +5764,12 @@ operand cmpOp() %{
format %{ "" %}
interface(COND_INTER) %{
equal(0x4);
not_equal(0x5);
less(0xC);
greater_equal(0xD);
less_equal(0xE);
greater(0xF);
equal(0x4, "e");
not_equal(0x5, "ne");
less(0xC, "l");
greater_equal(0xD, "ge");
less_equal(0xE, "le");
greater(0xF, "g");
%}
%}
@ -5766,12 +5781,47 @@ operand cmpOpU() %{
format %{ "" %}
interface(COND_INTER) %{
equal(0x4);
not_equal(0x5);
less(0x2);
greater_equal(0x3);
less_equal(0x6);
greater(0x7);
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x2, "b");
greater_equal(0x3, "nb");
less_equal(0x6, "be");
greater(0x7, "nbe");
%}
%}
// Floating comparisons that don't require any fixup for the unordered case
operand cmpOpUCF() %{
match(Bool);
predicate(n->as_Bool()->_test._test == BoolTest::lt ||
n->as_Bool()->_test._test == BoolTest::ge ||
n->as_Bool()->_test._test == BoolTest::le ||
n->as_Bool()->_test._test == BoolTest::gt);
format %{ "" %}
interface(COND_INTER) %{
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x2, "b");
greater_equal(0x3, "nb");
less_equal(0x6, "be");
greater(0x7, "nbe");
%}
%}
// Floating comparisons that can be fixed up with extra conditional jumps
operand cmpOpUCF2() %{
match(Bool);
predicate(n->as_Bool()->_test._test == BoolTest::ne ||
n->as_Bool()->_test._test == BoolTest::eq);
format %{ "" %}
interface(COND_INTER) %{
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x2, "b");
greater_equal(0x3, "nb");
less_equal(0x6, "be");
greater(0x7, "nbe");
%}
%}
@ -5796,12 +5846,12 @@ operand cmpOp_commute() %{
format %{ "" %}
interface(COND_INTER) %{
equal(0x4);
not_equal(0x5);
less(0xF);
greater_equal(0xE);
less_equal(0xD);
greater(0xC);
equal(0x4, "e");
not_equal(0x5, "ne");
less(0xF, "g");
greater_equal(0xE, "le");
less_equal(0xD, "ge");
greater(0xC, "l");
%}
%}
@ -7357,7 +7407,7 @@ instruct cmovI_reg(eRegI dst, eRegI src, eFlagsReg cr, cmpOp cop ) %{
ins_pipe( pipe_cmov_reg );
%}
instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{
instruct cmovI_regU( cmpOpU cop, eFlagsRegU cr, eRegI dst, eRegI src ) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200);
@ -7367,6 +7417,15 @@ instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{
ins_pipe( pipe_cmov_reg );
%}
instruct cmovI_regUCF( cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, eRegI src ) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovI_regU(cop, cr, dst, src);
%}
%}
// Conditional move
instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{
predicate(VM_Version::supports_cmov() );
@ -7379,7 +7438,7 @@ instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{
%}
// Conditional move
instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{
instruct cmovI_memU(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250);
@ -7389,6 +7448,15 @@ instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{
ins_pipe( pipe_cmov_mem );
%}
instruct cmovI_memUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, memory src) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250);
expand %{
cmovI_memU(cop, cr, dst, src);
%}
%}
// Conditional move
instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{
predicate(VM_Version::supports_cmov() );
@ -7416,7 +7484,7 @@ instruct cmovP_reg_nonP6(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{
%}
// Conditional move
instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{
instruct cmovP_regU(cmpOpU cop, eFlagsRegU cr, eRegP dst, eRegP src ) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200);
@ -7426,6 +7494,15 @@ instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{
ins_pipe( pipe_cmov_reg );
%}
instruct cmovP_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegP dst, eRegP src ) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovP_regU(cop, cr, dst, src);
%}
%}
// DISABLED: Requires the ADLC to emit a bottom_type call that
// correctly meets the two pointer arguments; one is an incoming
// register but the other is a memory operand. ALSO appears to
@ -7555,6 +7632,15 @@ instruct fcmovX_regU(cmpOpU cop, eFlagsRegU cr, regX dst, regX src) %{
ins_pipe( pipe_slow );
%}
instruct fcmovX_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regX dst, regX src) %{
predicate (UseSSE>=1);
match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
fcmovX_regU(cop, cr, dst, src);
%}
%}
// unsigned version
instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{
predicate (UseSSE>=2);
@ -7573,6 +7659,15 @@ instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{
ins_pipe( pipe_slow );
%}
instruct fcmovXD_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regXD dst, regXD src) %{
predicate (UseSSE>=2);
match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
fcmovXD_regU(cop, cr, dst, src);
%}
%}
instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
@ -7595,6 +7690,15 @@ instruct cmovL_regU(cmpOpU cop, eFlagsRegU cr, eRegL dst, eRegL src) %{
ins_pipe( pipe_cmov_reg_long );
%}
instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{
predicate(VM_Version::supports_cmov() );
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovL_regU(cop, cr, dst, src);
%}
%}
//----------Arithmetic Instructions--------------------------------------------
//----------Addition Instructions----------------------------------------------
// Integer Addition Instructions
@ -7826,33 +7930,36 @@ instruct storePConditional( memory heap_top_ptr, eAXRegP oldval, eRegP newval, e
ins_pipe( pipe_cmpxchg );
%}
// Conditional-store of a long value
// Returns a boolean value (0/1) on success. Implemented with a CMPXCHG8 on Intel.
// mem_ptr can actually be in either ESI or EDI
instruct storeLConditional( eRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
match(Set res (StoreLConditional mem_ptr (Binary oldval newval)));
effect(KILL cr);
// EDX:EAX is killed if there is contention, but then it's also unused.
// In the common case of no contention, EDX:EAX holds the new oop address.
format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
"MOV $res,0\n\t"
"JNE,s fail\n\t"
"MOV $res,1\n"
"fail:" %}
ins_encode( enc_cmpxchg8(mem_ptr),
enc_flags_ne_to_boolean(res) );
// Conditional-store of an int value.
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG on Intel.
instruct storeIConditional( memory mem, eAXRegI oldval, eRegI newval, eFlagsReg cr ) %{
match(Set cr (StoreIConditional mem (Binary oldval newval)));
effect(KILL oldval);
format %{ "CMPXCHG $mem,$newval\t# If EAX==$mem Then store $newval into $mem" %}
ins_encode( lock_prefix, Opcode(0x0F), Opcode(0xB1), RegMem(newval, mem) );
ins_pipe( pipe_cmpxchg );
%}
// Conditional-store of a long value
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG8 on Intel.
// mem_ptr can actually be in either ESI or EDI
instruct storeLConditional_flags( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr, immI0 zero ) %{
match(Set cr (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero));
// EDX:EAX is killed if there is contention, but then it's also unused.
// In the common case of no contention, EDX:EAX holds the new oop address.
format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
ins_encode( enc_cmpxchg8(mem_ptr) );
// Conditional-store of a long value.
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG8 on Intel.
instruct storeLConditional( memory mem, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{
match(Set cr (StoreLConditional mem (Binary oldval newval)));
effect(KILL oldval);
format %{ "XCHG EBX,ECX\t# correct order for CMPXCHG8 instruction\n\t"
"CMPXCHG8 $mem,ECX:EBX\t# If EDX:EAX==$mem Then store ECX:EBX into $mem\n\t"
"XCHG EBX,ECX"
%}
ins_encode %{
// Note: we need to swap rbx, and rcx before and after the
// cmpxchg8 instruction because the instruction uses
// rcx as the high order word of the new value to store but
// our register encoding uses rbx.
__ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
if( os::is_MP() )
__ lock();
__ cmpxchg8(Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp));
__ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
%}
ins_pipe( pipe_cmpxchg );
%}
@ -8319,6 +8426,7 @@ instruct shrI_eReg_imm(eRegI dst, immI8 shift, eFlagsReg cr) %{
ins_pipe( ialu_reg );
%}
// Logical Shift Right by 24, followed by Arithmetic Shift Left by 24.
// This idiom is used by the compiler for the i2b bytecode.
instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour, eFlagsReg cr) %{
@ -8436,6 +8544,18 @@ instruct orI_eReg(eRegI dst, eRegI src, eFlagsReg cr) %{
ins_pipe( ialu_reg_reg );
%}
instruct orI_eReg_castP2X(eRegI dst, eRegP src, eFlagsReg cr) %{
match(Set dst (OrI dst (CastP2X src)));
effect(KILL cr);
size(2);
format %{ "OR $dst,$src" %}
opcode(0x0B);
ins_encode( OpcP, RegReg( dst, src) );
ins_pipe( ialu_reg_reg );
%}
// Or Register with Immediate
instruct orI_eReg_imm(eRegI dst, immI src, eFlagsReg cr) %{
match(Set dst (OrI dst src));
@ -9200,6 +9320,18 @@ instruct cmpD_cc_P6(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{
ins_pipe( pipe_slow );
%}
instruct cmpD_cc_P6CF(eFlagsRegUCF cr, regD src1, regD src2) %{
predicate(VM_Version::supports_cmov() && UseSSE <=1);
match(Set cr (CmpD src1 src2));
ins_cost(150);
format %{ "FLD $src1\n\t"
"FUCOMIP ST,$src2 // P6 instruction" %}
opcode(0xDF, 0x05); /* DF E8+i or DF /5 */
ins_encode( Push_Reg_D(src1),
OpcP, RegOpc(src2));
ins_pipe( pipe_slow );
%}
// Compare & branch
instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{
predicate(UseSSE<=1);
@ -9264,6 +9396,16 @@ instruct cmpXD_cc(eFlagsRegU cr, regXD dst, regXD src, eAXRegI rax) %{
ins_pipe( pipe_slow );
%}
instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD dst, regXD src) %{
predicate(UseSSE>=2);
match(Set cr (CmpD dst src));
ins_cost(100);
format %{ "COMISD $dst,$src" %}
opcode(0x66, 0x0F, 0x2F);
ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src));
ins_pipe( pipe_slow );
%}
// float compare and set condition codes in EFLAGS by XMM regs
instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{
predicate(UseSSE>=2);
@ -9280,6 +9422,16 @@ instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{
ins_pipe( pipe_slow );
%}
instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD dst, memory src) %{
predicate(UseSSE>=2);
match(Set cr (CmpD dst (LoadD src)));
ins_cost(100);
format %{ "COMISD $dst,$src" %}
opcode(0x66, 0x0F, 0x2F);
ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src));
ins_pipe( pipe_slow );
%}
// Compare into -1,0,1 in XMM
instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{
predicate(UseSSE>=2);
@ -10167,6 +10319,18 @@ instruct cmpF_cc_P6(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{
ins_pipe( pipe_slow );
%}
instruct cmpF_cc_P6CF(eFlagsRegUCF cr, regF src1, regF src2) %{
predicate(VM_Version::supports_cmov() && UseSSE == 0);
match(Set cr (CmpF src1 src2));
ins_cost(100);
format %{ "FLD $src1\n\t"
"FUCOMIP ST,$src2 // P6 instruction" %}
opcode(0xDF, 0x05); /* DF E8+i or DF /5 */
ins_encode( Push_Reg_D(src1),
OpcP, RegOpc(src2));
ins_pipe( pipe_slow );
%}
// Compare & branch
instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{
@ -10232,6 +10396,16 @@ instruct cmpX_cc(eFlagsRegU cr, regX dst, regX src, eAXRegI rax) %{
ins_pipe( pipe_slow );
%}
instruct cmpX_ccCF(eFlagsRegUCF cr, regX dst, regX src) %{
predicate(UseSSE>=1);
match(Set cr (CmpF dst src));
ins_cost(100);
format %{ "COMISS $dst,$src" %}
opcode(0x0F, 0x2F);
ins_encode(OpcP, OpcS, RegReg(dst, src));
ins_pipe( pipe_slow );
%}
// float compare and set condition codes in EFLAGS by XMM regs
instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{
predicate(UseSSE>=1);
@ -10248,6 +10422,16 @@ instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{
ins_pipe( pipe_slow );
%}
instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX dst, memory src) %{
predicate(UseSSE>=1);
match(Set cr (CmpF dst (LoadF src)));
ins_cost(100);
format %{ "COMISS $dst,$src" %}
opcode(0x0F, 0x2F);
ins_encode(OpcP, OpcS, RegMem(dst, src));
ins_pipe( pipe_slow );
%}
// Compare into -1,0,1 in XMM
instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{
predicate(UseSSE>=1);
@ -12099,6 +12283,19 @@ instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_pc_relative(1);
%}
instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
match(CountedLoopEnd cop cmp);
effect(USE labl);
ins_cost(200);
format %{ "J$cop,u $labl\t# Loop end" %}
size(6);
opcode(0x0F, 0x80);
ins_encode( Jcc( cop, labl) );
ins_pipe( pipe_jcc );
ins_pc_relative(1);
%}
// Jump Direct Conditional - using unsigned comparison
instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
match(If cop cmp);
@ -12108,8 +12305,63 @@ instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
format %{ "J$cop,u $labl" %}
size(6);
opcode(0x0F, 0x80);
ins_encode( Jcc( cop, labl) );
ins_pipe( pipe_jcc );
ins_encode(Jcc(cop, labl));
ins_pipe(pipe_jcc);
ins_pc_relative(1);
%}
instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(200);
format %{ "J$cop,u $labl" %}
size(6);
opcode(0x0F, 0x80);
ins_encode(Jcc(cop, labl));
ins_pipe(pipe_jcc);
ins_pc_relative(1);
%}
instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(200);
format %{ $$template
if ($cop$$cmpcode == Assembler::notEqual) {
$$emit$$"JP,u $labl\n\t"
$$emit$$"J$cop,u $labl"
} else {
$$emit$$"JP,u done\n\t"
$$emit$$"J$cop,u $labl\n\t"
$$emit$$"done:"
}
%}
size(12);
opcode(0x0F, 0x80);
ins_encode %{
Label* l = $labl$$label;
$$$emit8$primary;
emit_cc(cbuf, $secondary, Assembler::parity);
int parity_disp = -1;
bool ok = false;
if ($cop$$cmpcode == Assembler::notEqual) {
// the two jumps 6 bytes apart so the jump distances are too
parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0;
} else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 6;
ok = true;
} else {
ShouldNotReachHere();
}
emit_d32(cbuf, parity_disp);
$$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode);
int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0;
emit_d32(cbuf, disp);
%}
ins_pipe(pipe_jcc);
ins_pc_relative(1);
%}
@ -12208,7 +12460,7 @@ instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{
effect(USE labl);
ins_cost(300);
format %{ "J$cop,s $labl" %}
format %{ "J$cop,s $labl\t# Loop end" %}
size(2);
opcode(0x70);
ins_encode( JccShort( cop, labl) );
@ -12223,7 +12475,21 @@ instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
effect(USE labl);
ins_cost(300);
format %{ "J$cop,us $labl" %}
format %{ "J$cop,us $labl\t# Loop end" %}
size(2);
opcode(0x70);
ins_encode( JccShort( cop, labl) );
ins_pipe( pipe_jcc );
ins_pc_relative(1);
ins_short_branch(1);
%}
instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
match(CountedLoopEnd cop cmp);
effect(USE labl);
ins_cost(300);
format %{ "J$cop,us $labl\t# Loop end" %}
size(2);
opcode(0x70);
ins_encode( JccShort( cop, labl) );
@ -12247,6 +12513,60 @@ instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{
ins_short_branch(1);
%}
instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(300);
format %{ "J$cop,us $labl" %}
size(2);
opcode(0x70);
ins_encode( JccShort( cop, labl) );
ins_pipe( pipe_jcc );
ins_pc_relative(1);
ins_short_branch(1);
%}
instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(300);
format %{ $$template
if ($cop$$cmpcode == Assembler::notEqual) {
$$emit$$"JP,u,s $labl\n\t"
$$emit$$"J$cop,u,s $labl"
} else {
$$emit$$"JP,u,s done\n\t"
$$emit$$"J$cop,u,s $labl\n\t"
$$emit$$"done:"
}
%}
size(4);
opcode(0x70);
ins_encode %{
Label* l = $labl$$label;
emit_cc(cbuf, $primary, Assembler::parity);
int parity_disp = -1;
if ($cop$$cmpcode == Assembler::notEqual) {
parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0;
} else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 2;
} else {
ShouldNotReachHere();
}
emit_d8(cbuf, parity_disp);
emit_cc(cbuf, $primary, $cop$$cmpcode);
int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0;
emit_d8(cbuf, disp);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp");
%}
ins_pipe(pipe_jcc);
ins_pc_relative(1);
ins_short_branch(1);
%}
// ============================================================================
// Long Compare
//

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
// this method should return false for offset 0.
bool Matcher::is_short_branch_offset(int offset)
{
return -0x80 <= offset && offset < 0x80;
bool Matcher::is_short_branch_offset(int rule, int offset) {
// the short version of jmpConUCF2 contains multiple branches,
// making the reach slightly less
if (rule == jmpConUCF2_rule)
return (-126 <= offset && offset <= 125);
return (-128 <= offset && offset <= 127);
}
const bool Matcher::isSimpleConstant64(jlong value) {
@ -3569,7 +3572,7 @@ encode %{
// at [FETCH], below, will never observe a biased encoding (*101b).
// If this invariant is not held we'll suffer exclusion (safety) failure.
if (UseBiasedLocking) {
if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters);
masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH]
}
@ -3657,7 +3660,7 @@ encode %{
} else {
Label DONE_LABEL, Stacked, CheckSucc ;
if (UseBiasedLocking) {
if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
}
@ -5134,6 +5137,15 @@ operand rFlagsRegU()
interface(REG_INTER);
%}
operand rFlagsRegUCF() %{
constraint(ALLOC_IN_RC(int_flags));
match(RegFlags);
predicate(false);
format %{ "RFLAGS_U_CF" %}
interface(REG_INTER);
%}
// Float register operands
operand regF()
%{
@ -5405,12 +5417,12 @@ operand cmpOp()
format %{ "" %}
interface(COND_INTER) %{
equal(0x4);
not_equal(0x5);
less(0xC);
greater_equal(0xD);
less_equal(0xE);
greater(0xF);
equal(0x4, "e");
not_equal(0x5, "ne");
less(0xC, "l");
greater_equal(0xD, "ge");
less_equal(0xE, "le");
greater(0xF, "g");
%}
%}
@ -5423,12 +5435,48 @@ operand cmpOpU()
format %{ "" %}
interface(COND_INTER) %{
equal(0x4);
not_equal(0x5);
less(0x2);
greater_equal(0x3);
less_equal(0x6);
greater(0x7);
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x2, "b");
greater_equal(0x3, "nb");
less_equal(0x6, "be");
greater(0x7, "nbe");
%}
%}
// Floating comparisons that don't require any fixup for the unordered case
operand cmpOpUCF() %{
match(Bool);
predicate(n->as_Bool()->_test._test == BoolTest::lt ||
n->as_Bool()->_test._test == BoolTest::ge ||
n->as_Bool()->_test._test == BoolTest::le ||
n->as_Bool()->_test._test == BoolTest::gt);
format %{ "" %}
interface(COND_INTER) %{
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x2, "b");
greater_equal(0x3, "nb");
less_equal(0x6, "be");
greater(0x7, "nbe");
%}
%}
// Floating comparisons that can be fixed up with extra conditional jumps
operand cmpOpUCF2() %{
match(Bool);
predicate(n->as_Bool()->_test._test == BoolTest::ne ||
n->as_Bool()->_test._test == BoolTest::eq);
format %{ "" %}
interface(COND_INTER) %{
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x2, "b");
greater_equal(0x3, "nb");
less_equal(0x6, "be");
greater(0x7, "nbe");
%}
%}
@ -7176,8 +7224,7 @@ instruct cmovI_reg(rRegI dst, rRegI src, rFlagsReg cr, cmpOp cop)
ins_pipe(pipe_cmov_reg);
%}
instruct cmovI_regU(rRegI dst, rRegI src, rFlagsRegU cr, cmpOpU cop)
%{
instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200); // XXX
@ -7187,9 +7234,16 @@ instruct cmovI_regU(rRegI dst, rRegI src, rFlagsRegU cr, cmpOpU cop)
ins_pipe(pipe_cmov_reg);
%}
instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovI_regU(cop, cr, dst, src);
%}
%}
// Conditional move
instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src)
%{
instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250); // XXX
@ -7211,6 +7265,14 @@ instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
ins_pipe(pipe_cmov_mem);
%}
instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
ins_cost(250);
expand %{
cmovI_memU(cop, cr, dst, src);
%}
%}
// Conditional move
instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
%{
@ -7224,7 +7286,7 @@ instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
%}
// Conditional move
instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop)
instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src)
%{
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
@ -7235,6 +7297,14 @@ instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop)
ins_pipe(pipe_cmov_reg);
%}
instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovN_regU(cop, cr, dst, src);
%}
%}
// Conditional move
instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
%{
@ -7248,7 +7318,7 @@ instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
%}
// Conditional move
instruct cmovP_regU(rRegP dst, rRegP src, rFlagsRegU cr, cmpOpU cop)
instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src)
%{
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
@ -7259,6 +7329,14 @@ instruct cmovP_regU(rRegP dst, rRegP src, rFlagsRegU cr, cmpOpU cop)
ins_pipe(pipe_cmov_reg); // XXX
%}
instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovP_regU(cop, cr, dst, src);
%}
%}
// DISABLED: Requires the ADLC to emit a bottom_type call that
// correctly meets the two pointer arguments; one is an incoming
// register but the other is a memory operand. ALSO appears to
@ -7319,6 +7397,14 @@ instruct cmovL_regU(cmpOpU cop, rFlagsRegU cr, rRegL dst, rRegL src)
ins_pipe(pipe_cmov_reg); // XXX
%}
instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovL_regU(cop, cr, dst, src);
%}
%}
instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
%{
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
@ -7330,6 +7416,14 @@ instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
ins_pipe(pipe_cmov_mem); // XXX
%}
instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
ins_cost(200);
expand %{
cmovL_memU(cop, cr, dst, src);
%}
%}
instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src)
%{
match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
@ -7366,6 +7460,14 @@ instruct cmovF_regU(cmpOpU cop, rFlagsRegU cr, regF dst, regF src)
ins_pipe(pipe_slow);
%}
instruct cmovF_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regF dst, regF src) %{
match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovF_regU(cop, cr, dst, src);
%}
%}
instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src)
%{
match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
@ -7390,6 +7492,14 @@ instruct cmovD_regU(cmpOpU cop, rFlagsRegU cr, regD dst, regD src)
ins_pipe(pipe_slow);
%}
instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{
match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
ins_cost(200);
expand %{
cmovD_regU(cop, cr, dst, src);
%}
%}
//----------Arithmetic Instructions--------------------------------------------
//----------Addition Instructions----------------------------------------------
@ -7735,7 +7845,7 @@ instruct storePConditional(memory heap_top_ptr,
rFlagsReg cr)
%{
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
"If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
opcode(0x0F, 0xB1);
@ -7746,53 +7856,40 @@ instruct storePConditional(memory heap_top_ptr,
ins_pipe(pipe_cmpxchg);
%}
// Conditional-store of a long value
// Returns a boolean value (0/1) on success. Implemented with a
// CMPXCHG8 on Intel. mem_ptr can actually be in either RSI or RDI
instruct storeLConditional(rRegI res,
memory mem_ptr,
rax_RegL oldval, rRegL newval,
rFlagsReg cr)
// Conditional-store of an int value.
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG.
instruct storeIConditional(memory mem, rax_RegI oldval, rRegI newval, rFlagsReg cr)
%{
match(Set res (StoreLConditional mem_ptr (Binary oldval newval)));
effect(KILL cr);
match(Set cr (StoreIConditional mem (Binary oldval newval)));
effect(KILL oldval);
format %{ "cmpxchgq $mem_ptr, $newval\t# (long) "
"If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
"sete $res\n\t"
"movzbl $res, $res" %}
format %{ "cmpxchgl $mem, $newval\t# If rax == $mem then store $newval into $mem" %}
opcode(0x0F, 0xB1);
ins_encode(lock_prefix,
REX_reg_mem_wide(newval, mem_ptr),
REX_reg_mem(newval, mem),
OpcP, OpcS,
reg_mem(newval, mem_ptr),
REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete
REX_reg_breg(res, res), // movzbl
Opcode(0xF), Opcode(0xB6), reg_reg(res, res));
reg_mem(newval, mem));
ins_pipe(pipe_cmpxchg);
%}
// Conditional-store of a long value
// ZF flag is set on success, reset otherwise. Implemented with a
// CMPXCHG8 on Intel. mem_ptr can actually be in either RSI or RDI
instruct storeLConditional_flags(memory mem_ptr,
rax_RegL oldval, rRegL newval,
rFlagsReg cr,
immI0 zero)
// Conditional-store of a long value.
// ZF flag is set on success, reset otherwise. Implemented with a CMPXCHG.
instruct storeLConditional(memory mem, rax_RegL oldval, rRegL newval, rFlagsReg cr)
%{
match(Set cr (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero));
match(Set cr (StoreLConditional mem (Binary oldval newval)));
effect(KILL oldval);
format %{ "cmpxchgq $mem_ptr, $newval\t# (long) "
"If rax == $mem_ptr then store $newval into $mem_ptr" %}
format %{ "cmpxchgq $mem, $newval\t# If rax == $mem then store $newval into $mem" %}
opcode(0x0F, 0xB1);
ins_encode(lock_prefix,
REX_reg_mem_wide(newval, mem_ptr),
REX_reg_mem_wide(newval, mem),
OpcP, OpcS,
reg_mem(newval, mem_ptr));
reg_mem(newval, mem));
ins_pipe(pipe_cmpxchg);
%}
// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
instruct compareAndSwapP(rRegI res,
memory mem_ptr,
rax_RegP oldval, rRegP newval,
@ -7816,7 +7913,6 @@ instruct compareAndSwapP(rRegI res,
ins_pipe( pipe_cmpxchg );
%}
// XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
instruct compareAndSwapL(rRegI res,
memory mem_ptr,
rax_RegL oldval, rRegL newval,
@ -8766,6 +8862,7 @@ instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
// Logical Shift Right by 8-bit immediate
instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
%{
@ -9475,6 +9572,18 @@ instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
ins_pipe(ialu_reg_reg);
%}
// Use any_RegP to match R15 (TLS register) without spilling.
instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{
match(Set dst (OrL dst (CastP2X src)));
effect(KILL cr);
format %{ "orq $dst, $src\t# long" %}
opcode(0x0B);
ins_encode(REX_reg_reg_wide(dst, src), OpcP, reg_reg(dst, src));
ins_pipe(ialu_reg_reg);
%}
// Or Register with Immediate
instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
%{
@ -9716,6 +9825,17 @@ instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2)
ins_pipe(pipe_slow);
%}
instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{
match(Set cr (CmpF src1 src2));
ins_cost(145);
format %{ "ucomiss $src1, $src2" %}
ins_encode %{
__ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
%}
ins_pipe(pipe_slow);
%}
instruct cmpF_cc_mem(rFlagsRegU cr, regF src1, memory src2)
%{
match(Set cr (CmpF src1 (LoadF src2)));
@ -9733,6 +9853,16 @@ instruct cmpF_cc_mem(rFlagsRegU cr, regF src1, memory src2)
ins_pipe(pipe_slow);
%}
instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{
match(Set cr (CmpF src1 (LoadF src2)));
ins_cost(100);
format %{ "ucomiss $src1, $src2" %}
opcode(0x0F, 0x2E);
ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2));
ins_pipe(pipe_slow);
%}
instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2)
%{
match(Set cr (CmpF src1 src2));
@ -9750,6 +9880,16 @@ instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2)
ins_pipe(pipe_slow);
%}
instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{
match(Set cr (CmpF src1 src2));
ins_cost(100);
format %{ "ucomiss $src1, $src2" %}
opcode(0x0F, 0x2E);
ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2));
ins_pipe(pipe_slow);
%}
instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
%{
match(Set cr (CmpD src1 src2));
@ -9767,6 +9907,17 @@ instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
ins_pipe(pipe_slow);
%}
instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{
match(Set cr (CmpD src1 src2));
ins_cost(100);
format %{ "ucomisd $src1, $src2 test" %}
ins_encode %{
__ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
%}
ins_pipe(pipe_slow);
%}
instruct cmpD_cc_mem(rFlagsRegU cr, regD src1, memory src2)
%{
match(Set cr (CmpD src1 (LoadD src2)));
@ -9784,6 +9935,16 @@ instruct cmpD_cc_mem(rFlagsRegU cr, regD src1, memory src2)
ins_pipe(pipe_slow);
%}
instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{
match(Set cr (CmpD src1 (LoadD src2)));
ins_cost(100);
format %{ "ucomisd $src1, $src2" %}
opcode(0x66, 0x0F, 0x2E);
ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2));
ins_pipe(pipe_slow);
%}
instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2)
%{
match(Set cr (CmpD src1 src2));
@ -9801,6 +9962,16 @@ instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2)
ins_pipe(pipe_slow);
%}
instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{
match(Set cr (CmpD src1 src2));
ins_cost(100);
format %{ "ucomisd $src1, [$src2]" %}
opcode(0x66, 0x0F, 0x2E);
ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2));
ins_pipe(pipe_slow);
%}
// Compare into -1,0,1
instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr)
%{
@ -11406,8 +11577,7 @@ instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl)
%}
// Jump Direct Conditional - Label defines a relative address from Jcc+1
instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl)
%{
instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
match(CountedLoopEnd cop cmp);
effect(USE labl);
@ -11420,14 +11590,26 @@ instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_pc_relative(1);
%}
instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
match(CountedLoopEnd cop cmp);
effect(USE labl);
ins_cost(200);
format %{ "j$cop,u $labl\t# loop end" %}
size(6);
opcode(0x0F, 0x80);
ins_encode(Jcc(cop, labl));
ins_pipe(pipe_jcc);
ins_pc_relative(1);
%}
// Jump Direct Conditional - using unsigned comparison
instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl)
%{
instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(300);
format %{ "j$cop,u $labl" %}
format %{ "j$cop,u $labl" %}
size(6);
opcode(0x0F, 0x80);
ins_encode(Jcc(cop, labl));
@ -11435,6 +11617,59 @@ instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_pc_relative(1);
%}
instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(200);
format %{ "j$cop,u $labl" %}
size(6);
opcode(0x0F, 0x80);
ins_encode(Jcc(cop, labl));
ins_pipe(pipe_jcc);
ins_pc_relative(1);
%}
instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(200);
format %{ $$template
if ($cop$$cmpcode == Assembler::notEqual) {
$$emit$$"jp,u $labl\n\t"
$$emit$$"j$cop,u $labl"
} else {
$$emit$$"jp,u done\n\t"
$$emit$$"j$cop,u $labl\n\t"
$$emit$$"done:"
}
%}
size(12);
opcode(0x0F, 0x80);
ins_encode %{
Label* l = $labl$$label;
$$$emit8$primary;
emit_cc(cbuf, $secondary, Assembler::parity);
int parity_disp = -1;
if ($cop$$cmpcode == Assembler::notEqual) {
// the two jumps 6 bytes apart so the jump distances are too
parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0;
} else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 6;
} else {
ShouldNotReachHere();
}
emit_d32(cbuf, parity_disp);
$$$emit8$primary;
emit_cc(cbuf, $secondary, $cop$$cmpcode);
int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0;
emit_d32(cbuf, disp);
%}
ins_pipe(pipe_jcc);
ins_pc_relative(1);
%}
// ============================================================================
// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary
// superklass array for an instance of the superklass. Set a hidden
@ -11505,8 +11740,7 @@ instruct partialSubtypeCheck_vs_Zero(rFlagsReg cr,
// specific code section of the file.
// Jump Direct - Label defines a relative address from JMP+1
instruct jmpDir_short(label labl)
%{
instruct jmpDir_short(label labl) %{
match(Goto);
effect(USE labl);
@ -11521,8 +11755,7 @@ instruct jmpDir_short(label labl)
%}
// Jump Direct Conditional - Label defines a relative address from Jcc+1
instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl)
%{
instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{
match(If cop cr);
effect(USE labl);
@ -11537,13 +11770,12 @@ instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl)
%}
// Jump Direct Conditional - Label defines a relative address from Jcc+1
instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl)
%{
instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{
match(CountedLoopEnd cop cr);
effect(USE labl);
ins_cost(300);
format %{ "j$cop,s $labl" %}
format %{ "j$cop,s $labl\t# loop end" %}
size(2);
opcode(0x70);
ins_encode(JccShort(cop, labl));
@ -11553,11 +11785,39 @@ instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl)
%}
// Jump Direct Conditional - Label defines a relative address from Jcc+1
instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
%{
instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{
match(CountedLoopEnd cop cmp);
effect(USE labl);
ins_cost(300);
format %{ "j$cop,us $labl\t# loop end" %}
size(2);
opcode(0x70);
ins_encode(JccShort(cop, labl));
ins_pipe(pipe_jcc);
ins_pc_relative(1);
ins_short_branch(1);
%}
instruct jmpLoopEndUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
match(CountedLoopEnd cop cmp);
effect(USE labl);
ins_cost(300);
format %{ "j$cop,us $labl\t# loop end" %}
size(2);
opcode(0x70);
ins_encode(JccShort(cop, labl));
ins_pipe(pipe_jcc);
ins_pc_relative(1);
ins_short_branch(1);
%}
// Jump Direct Conditional - using unsigned comparison
instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(300);
format %{ "j$cop,us $labl" %}
size(2);
@ -11568,9 +11828,7 @@ instruct jmpLoopEndU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_short_branch(1);
%}
// Jump Direct Conditional - using unsigned comparison
instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
%{
instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
@ -11584,6 +11842,46 @@ instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl)
ins_short_branch(1);
%}
instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
match(If cop cmp);
effect(USE labl);
ins_cost(300);
format %{ $$template
if ($cop$$cmpcode == Assembler::notEqual) {
$$emit$$"jp,u,s $labl\n\t"
$$emit$$"j$cop,u,s $labl"
} else {
$$emit$$"jp,u,s done\n\t"
$$emit$$"j$cop,u,s $labl\n\t"
$$emit$$"done:"
}
%}
size(4);
opcode(0x70);
ins_encode %{
Label* l = $labl$$label;
emit_cc(cbuf, $primary, Assembler::parity);
int parity_disp = -1;
if ($cop$$cmpcode == Assembler::notEqual) {
parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0;
} else if ($cop$$cmpcode == Assembler::equal) {
parity_disp = 2;
} else {
ShouldNotReachHere();
}
emit_d8(cbuf, parity_disp);
emit_cc(cbuf, $primary, $cop$$cmpcode);
int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0;
emit_d8(cbuf, disp);
assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp");
%}
ins_pipe(pipe_jcc);
ins_pc_relative(1);
ins_short_branch(1);
%}
// ============================================================================
// inlined locking and unlocking

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,7 +37,7 @@ import java.util.Set;
*
* @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 transient ChangedEvent<Group> changedEvent;

View File

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

View File

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

View File

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

View File

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

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

View File

@ -67,7 +67,7 @@ public class Printer {
private void export(XMLWriter writer, Group g) throws IOException {
Properties attributes = new Properties();
attributes.add(new Property("difference", Boolean.toString(true)));
attributes.setProperty("difference", Boolean.toString(true));
writer.startTag(Parser.GROUP_ELEMENT, attributes);
writer.writeProperties(g.getProperties());

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,7 +42,7 @@ import java.util.Set;
*
* @author Thomas Wuerthinger
*/
public class Figure extends Properties.Object implements Source.Provider, Vertex {
public class Figure extends Properties.Entity implements Source.Provider, Vertex {
public static final int INSET = 6;
public static final int SLOT_WIDTH = 10;

View File

@ -26,7 +26,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
@ -37,13 +37,13 @@ import java.util.Queue;
*/
public class Graph<N, E> {
private Hashtable<Object, Node<N, E>> nodes;
private Hashtable<Object, Edge<N, E>> edges;
private HashMap<Object, Node<N, E>> nodes;
private HashMap<Object, Edge<N, E>> edges;
private List<Node<N, E>> nodeList;
public Graph() {
nodes = new Hashtable<Object, Node<N, E>>();
edges = new Hashtable<Object, Edge<N, E>>();
nodes = new HashMap<Object, Node<N, E>>();
edges = new HashMap<Object, Edge<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.Rectangle;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.ArrayList;
@ -69,19 +69,19 @@ public class HierarchicalClusterLayoutManager implements LayoutManager {
assert graph.verify();
Hashtable<Cluster, List<Vertex>> lists = new Hashtable<Cluster, List<Vertex>>();
Hashtable<Cluster, List<Link>> listsConnection = new Hashtable<Cluster, List<Link>>();
Hashtable<Cluster, Hashtable<Port, ClusterInputSlotNode>> clusterInputSlotHash = new Hashtable<Cluster, Hashtable<Port, ClusterInputSlotNode>>();
Hashtable<Cluster, Hashtable<Port, ClusterOutputSlotNode>> clusterOutputSlotHash = new Hashtable<Cluster, Hashtable<Port, ClusterOutputSlotNode>>();
HashMap<Cluster, List<Vertex>> lists = new HashMap<Cluster, List<Vertex>>();
HashMap<Cluster, List<Link>> listsConnection = new HashMap<Cluster, List<Link>>();
HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>> clusterInputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>>();
HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>> clusterOutputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>>();
Hashtable<Cluster, ClusterNode> clusterNodes = new Hashtable<Cluster, ClusterNode>();
Hashtable<Cluster, Set<ClusterInputSlotNode>> clusterInputSlotSet = new Hashtable<Cluster, Set<ClusterInputSlotNode>>();
Hashtable<Cluster, Set<ClusterOutputSlotNode>> clusterOutputSlotSet = new Hashtable<Cluster, Set<ClusterOutputSlotNode>>();
HashMap<Cluster, ClusterNode> clusterNodes = new HashMap<Cluster, ClusterNode>();
HashMap<Cluster, Set<ClusterInputSlotNode>> clusterInputSlotSet = new HashMap<Cluster, Set<ClusterInputSlotNode>>();
HashMap<Cluster, Set<ClusterOutputSlotNode>> clusterOutputSlotSet = new HashMap<Cluster, Set<ClusterOutputSlotNode>>();
Set<Link> clusterEdges = new HashSet<Link>();
Set<Link> interClusterEdges = new HashSet<Link>();
Hashtable<Link, ClusterOutgoingConnection> linkClusterOutgoingConnection = new Hashtable<Link, ClusterOutgoingConnection>();
Hashtable<Link, InterClusterConnection> linkInterClusterConnection = new Hashtable<Link, InterClusterConnection>();
Hashtable<Link, ClusterIngoingConnection> linkClusterIngoingConnection = new Hashtable<Link, ClusterIngoingConnection>();
HashMap<Link, ClusterOutgoingConnection> linkClusterOutgoingConnection = new HashMap<Link, ClusterOutgoingConnection>();
HashMap<Link, InterClusterConnection> linkInterClusterConnection = new HashMap<Link, InterClusterConnection>();
HashMap<Link, ClusterIngoingConnection> linkClusterIngoingConnection = new HashMap<Link, ClusterIngoingConnection>();
Set<ClusterNode> clusterNodeSet = new HashSet<ClusterNode>();
Set<Cluster> cluster = graph.getClusters();
@ -89,8 +89,8 @@ public class HierarchicalClusterLayoutManager implements LayoutManager {
for (Cluster c : cluster) {
lists.put(c, new ArrayList<Vertex>());
listsConnection.put(c, new ArrayList<Link>());
clusterInputSlotHash.put(c, new Hashtable<Port, ClusterInputSlotNode>());
clusterOutputSlotHash.put(c, new Hashtable<Port, ClusterOutputSlotNode>());
clusterInputSlotHash.put(c, new HashMap<Port, ClusterInputSlotNode>());
clusterOutputSlotHash.put(c, new HashMap<Port, ClusterOutputSlotNode>());
clusterOutputSlotSet.put(c, new TreeSet<ClusterOutputSlotNode>());
clusterInputSlotSet.put(c, new TreeSet<ClusterInputSlotNode>());
ClusterNode cn = new ClusterNode(c, "" + z);

View File

@ -24,7 +24,7 @@
package com.sun.hotspot.igv.layout;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
@ -37,9 +37,9 @@ public class LayoutGraph {
private Set<? extends Link> links;
private SortedSet<Vertex> vertices;
private Hashtable<Vertex, Set<Port>> inputPorts;
private Hashtable<Vertex, Set<Port>> outputPorts;
private Hashtable<Port, Set<Link>> portLinks;
private HashMap<Vertex, Set<Port>> inputPorts;
private HashMap<Vertex, Set<Port>> outputPorts;
private HashMap<Port, Set<Link>> portLinks;
public LayoutGraph(Set<? extends Link> links) {
this(links, new HashSet<Vertex>());
@ -50,9 +50,9 @@ public class LayoutGraph {
assert verify();
vertices = new TreeSet<Vertex>();
portLinks = new Hashtable<Port, Set<Link>>();
inputPorts = new Hashtable<Vertex, Set<Port>>();
outputPorts = new Hashtable<Vertex, Set<Port>>();
portLinks = new HashMap<Port, Set<Link>>();
inputPorts = new HashMap<Vertex, Set<Port>>();
outputPorts = new HashMap<Vertex, Set<Port>>();
for (Link l : links) {
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
with only a few modules that contain C2 specific elements.
The tool is built on top of the NetBeans 6.0 rich client
The tool is built on top of the NetBeans 6.1 rich client
infrastructure and so requires NetBeans to build. It currently
requires Java 6 to run as it needs support for JavaScript for its
filtering mechanism and assumes it's built into the platform. It
should build out of the box whit NetBeans 6 and Java 6 or later. It's
possible to run it on 1.5 by including Rhino on the classpath though
that currently isn't working correctly. Support for exporting graphs
as SVG can be enabled by adding batik to the classpath which isn't
included by default.
It can be built on top of NetBeans 6.1 if you change the required
modules to be platform8 instead of platform7. The tool could run on
JDK 1.5 with some reworking of the how the JavaScript support is
enabled but currently it requires some tweaking of the setup. This
will be fixed in a later setup.
should build out of the box with NetBeans 6.1 and Java 6 or later.
It's possible to run it on 1.5 by including Rhino on the classpath
though that currently isn't working correctly. Support for exporting
graphs as SVG can be enabled by adding batik to the classpath which
isn't included by default. It can be built on top of NetBeans 6.0 if
you change the required modules to be platform7 instead of platform8.
The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=#
where # is:

View File

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

View File

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

View File

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

View File

@ -55,6 +55,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
private FilterChain filterChain;
private FilterChain sequenceFilterChain;
private Diagram diagram;
private ChangedEvent<DiagramViewModel> groupChangedEvent;
private ChangedEvent<DiagramViewModel> diagramChangedEvent;
private ChangedEvent<DiagramViewModel> viewChangedEvent;
private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
@ -67,6 +68,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
}
};
@Override
public DiagramViewModel copy() {
DiagramViewModel result = new DiagramViewModel(group, filterChain, sequenceFilterChain);
result.setData(this);
@ -79,6 +81,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
boolean viewChanged = false;
boolean viewPropertiesChanged = false;
boolean groupChanged = (group == newModel.group);
this.group = newModel.group;
diagramChanged |= (filterChain != newModel.filterChain);
this.filterChain = newModel.filterChain;
@ -97,6 +100,10 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
this.showNodeHull = newModel.showNodeHull;
if(groupChanged) {
groupChangedEvent.fire();
}
if (diagramChanged) {
diagramChangedEvent.fire();
}
@ -143,11 +150,38 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
diagramChangedEvent = new ChangedEvent<DiagramViewModel>(this);
viewChangedEvent = new ChangedEvent<DiagramViewModel>(this);
viewPropertiesChangedEvent = new ChangedEvent<DiagramViewModel>(this);
groupChangedEvent = new ChangedEvent<DiagramViewModel>(this);
groupChangedEvent.addListener(groupChangedListener);
groupChangedEvent.fire();
filterChain.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() {
return diagramChangedEvent;
}
@ -268,7 +302,10 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
}
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) {

View File

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

View File

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

View File

@ -15,7 +15,6 @@ modules=\
${project.com.sun.hotspot.igv.difference}:\
${project.com.sun.hotspot.igv.settings}:\
${project.com.sun.hotspot.igv.util}:\
${project.com.sun.hotspot.igv.rhino}:\
${project.com.sun.hotspot.igv.svg}:\
${project.com.sun.hotspot.connection}:\
${project.com.sun.hotspot.igv.servercompilerscheduler}:\
@ -31,10 +30,10 @@ project.com.sun.hotspot.igv.filterwindow=FilterWindow
project.com.sun.hotspot.igv.graph=Graph
project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout
project.com.sun.hotspot.igv.layout=Layout
project.com.sun.hotspot.igv.rhino=RhinoScriptEngineProxy
project.com.sun.hotspot.igv.servercompilerscheduler=ServerCompiler
project.com.sun.hotspot.igv.settings=Settings
project.com.sun.hotspot.igv.svg=BatikSVGProxy
project.com.sun.hotspot.igv.view=View
project.com.sun.hotspot.igv.util=Util
run.args = -server -J-Xms64m -J-Xmx512m -J-da
run.args = -J-server -J-Xms64m -J-Xmx1g -J-da
run.args.extra = -J-server -J-Xms64m -J-Xmx1g -J-da

View File

@ -33,7 +33,6 @@ ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc)
_globalNames(archDesc.globalNames()) {
_AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
_AD._warnings = 0; // No warnings either
_linenum = 0; // Will increment to first line
_curline = _ptr = NULL; // No pointers into buffer yet
_preproc_depth = 0;
@ -76,7 +75,7 @@ ADLParser::~ADLParser() {
}
if (!_AD._quiet_mode)
fprintf(stderr,"-----------------------------------------------------------------------------\n");
_AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine
_AD._TotalLines += linenum()-1; // -1 for overshoot in "nextline" routine
// Write out information we have stored
// // UNIXism == fsync(stderr);
@ -148,7 +147,7 @@ void ADLParser::instr_parse(void) {
if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
return;
instr = new InstructForm(ident); // Create new instruction form
instr->_linenum = _linenum;
instr->_linenum = linenum();
_globalNames.Insert(ident, instr); // Add name to the name table
// Debugging Stuff
if (_AD._adl_debug > 1)
@ -404,7 +403,7 @@ void ADLParser::oper_parse(void) {
if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
return;
oper = new OperandForm(ident); // Create new operand form
oper->_linenum = _linenum;
oper->_linenum = linenum();
_globalNames.Insert(ident, oper); // Add name to the name table
// Debugging Stuff
@ -774,7 +773,7 @@ void ADLParser::reg_parse(void) {
// Create the RegisterForm for the architecture description.
RegisterForm *regBlock = new RegisterForm(); // Build new Source object
regBlock->_linenum = _linenum;
regBlock->_linenum = linenum();
_AD.addForm(regBlock);
skipws(); // Skip leading whitespace
@ -847,7 +846,7 @@ void ADLParser::enc_class_parse(void) {
}
EncClass *encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = _linenum;
encoding->_linenum = linenum();
skipws(); // Skip leading whitespace
// Check for optional parameter list
@ -905,7 +904,7 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
if (_AD._adlocation_debug) {
const char* file = _AD._ADL_file._name;
int line = _linenum;
int line = linenum();
char* location = (char *)malloc(strlen(file) + 100);
sprintf(location, "#line %d \"%s\"\n", line, file);
encoding->add_code(location);
@ -2776,7 +2775,7 @@ InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
EncClass *encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = _linenum;
encoding->_linenum = linenum();
// synthesize the arguments list for the enc_class from the
// arguments to the instruct definition.
@ -2852,7 +2851,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
skipws();
InsEncode *encrule = new InsEncode(); // Encode class for instruction
encrule->_linenum = _linenum;
encrule->_linenum = linenum();
char *ec_name = NULL; // String representation of encode rule
// identifier is optional.
while (_curchar != ')') {
@ -3203,6 +3202,12 @@ Interface *ADLParser::cond_interface_parse(void) {
char *greater_equal;
char *less_equal;
char *greater;
const char *equal_format = "eq";
const char *not_equal_format = "ne";
const char *less_format = "lt";
const char *greater_equal_format = "ge";
const char *less_equal_format = "le";
const char *greater_format = "gt";
if (_curchar != '%') {
parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
@ -3222,22 +3227,22 @@ Interface *ADLParser::cond_interface_parse(void) {
return NULL;
}
if ( strcmp(field,"equal") == 0 ) {
equal = interface_field_parse();
equal = interface_field_parse(&equal_format);
}
else if ( strcmp(field,"not_equal") == 0 ) {
not_equal = interface_field_parse();
not_equal = interface_field_parse(&not_equal_format);
}
else if ( strcmp(field,"less") == 0 ) {
less = interface_field_parse();
less = interface_field_parse(&less_format);
}
else if ( strcmp(field,"greater_equal") == 0 ) {
greater_equal = interface_field_parse();
greater_equal = interface_field_parse(&greater_equal_format);
}
else if ( strcmp(field,"less_equal") == 0 ) {
less_equal = interface_field_parse();
less_equal = interface_field_parse(&less_equal_format);
}
else if ( strcmp(field,"greater") == 0 ) {
greater = interface_field_parse();
greater = interface_field_parse(&greater_format);
}
else {
parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n");
@ -3252,14 +3257,18 @@ Interface *ADLParser::cond_interface_parse(void) {
next_char(); // Skip '}'
// Construct desired object and return
Interface *inter = new CondInterface(equal, not_equal, less, greater_equal,
less_equal, greater);
Interface *inter = new CondInterface(equal, equal_format,
not_equal, not_equal_format,
less, less_format,
greater_equal, greater_equal_format,
less_equal, less_equal_format,
greater, greater_format);
return inter;
}
//------------------------------interface_field_parse--------------------------
char *ADLParser::interface_field_parse(void) {
char *ADLParser::interface_field_parse(const char ** format) {
char *iface_field = NULL;
// Get interface field
@ -3280,6 +3289,32 @@ char *ADLParser::interface_field_parse(void) {
return NULL;
}
skipws();
if (format != NULL && _curchar == ',') {
next_char();
skipws();
if (_curchar != '"') {
parse_err(SYNERR, "Missing '\"' in field format .\n");
return NULL;
}
next_char();
char *start = _ptr; // Record start of the next string
while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
if (_curchar == '\\') next_char(); // superquote
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
next_char();
}
if (_curchar != '"') {
parse_err(SYNERR, "Missing '\"' at end of field format .\n");
return NULL;
}
// If a string was found, terminate it and record in FormatRule
if ( start != _ptr ) {
*_ptr = '\0'; // Terminate the string
*format = start;
}
next_char();
skipws();
}
if (_curchar != ')') {
parse_err(SYNERR, "Missing ')' after interface field.\n");
return NULL;
@ -3342,6 +3377,12 @@ FormatRule* ADLParser::format_parse(void) {
next_char(); // Move past the '{'
skipws();
if (_curchar == '$') {
char* ident = get_rep_var_ident();
if (strcmp(ident, "$$template") == 0) return template_parse();
parse_err(SYNERR, "Unknown \"%s\" directive in format", ident);
return NULL;
}
// Check for the opening '"' inside the format description
if ( _curchar == '"' ) {
next_char(); // Move past the initial '"'
@ -3433,6 +3474,131 @@ FormatRule* ADLParser::format_parse(void) {
}
//------------------------------template_parse-----------------------------------
FormatRule* ADLParser::template_parse(void) {
char *desc = NULL;
FormatRule *format = (new FormatRule(desc));
skipws();
while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
// (1)
// Check if there is a string to pass through to output
char *start = _ptr; // Record start of the next string
while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
// If at the start of a comment, skip past it
if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
skipws_no_preproc();
} else {
// ELSE advance to the next character, or start of the next line
next_char_or_line();
}
}
// If a string was found, terminate it and record in EncClass
if ( start != _ptr ) {
*_ptr = '\0'; // Terminate the string
// Add flag to _strings list indicating we should check _rep_vars
format->_strings.addName(NameList::_signal2);
format->_strings.addName(start);
}
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
if ( _curchar == '$' ) {
// Found replacement Variable
char *rep_var = get_rep_var_ident_dup();
if (strcmp(rep_var, "$emit") == 0) {
// switch to normal format parsing
next_char();
next_char();
skipws();
// Check for the opening '"' inside the format description
if ( _curchar == '"' ) {
next_char(); // Move past the initial '"'
if( _curchar == '"' ) { // Handle empty format string case
*_ptr = '\0'; // Terminate empty string
format->_strings.addName(_ptr);
}
// Collect the parts of the format description
// (1) strings that are passed through to tty->print
// (2) replacement/substitution variable, preceeded by a '$'
// (3) multi-token ANSIY C style strings
while ( true ) {
if ( _curchar == '%' || _curchar == '\n' ) {
parse_err(SYNERR, "missing '\"' at end of format block");
return NULL;
}
// (1)
// Check if there is a string to pass through to output
char *start = _ptr; // Record start of the next string
while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
if (_curchar == '\\') next_char(); // superquote
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
next_char();
}
// If a string was found, terminate it and record in FormatRule
if ( start != _ptr ) {
*_ptr = '\0'; // Terminate the string
format->_strings.addName(start);
}
// (2)
// If we are at a replacement variable,
// copy it and record in FormatRule
if ( _curchar == '$' ) {
next_char(); // Move past the '$'
char* rep_var = get_ident(); // Nil terminate the variable name
rep_var = strdup(rep_var);// Copy the string
*_ptr = _curchar; // and replace Nil with original character
format->_rep_vars.addName(rep_var);
// Add flag to _strings list indicating we should check _rep_vars
format->_strings.addName(NameList::_signal);
}
// (3)
// Allow very long strings to be broken up,
// using the ANSI C syntax "foo\n" <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-----------------------------------
void ADLParser::effect_parse(InstructForm *instr) {
char* desc = NULL;
@ -3777,7 +3943,7 @@ char* ADLParser::find_cpp_block(const char* description) {
skipws_no_preproc(); // Skip leading whitespace
cppBlock = _ptr; // Point to start of expression
const char* file = _AD._ADL_file._name;
int line = _linenum;
int line = linenum();
next = _ptr + 1;
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
next_char_or_line();
@ -4297,11 +4463,11 @@ void ADLParser::parse_err(int flag, const char *fmt, ...) {
va_start(args, fmt);
if (flag == 1)
_AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
_AD._syntax_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
else if (flag == 2)
_AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
_AD._semantic_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
else
_AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args);
_AD._warnings += _AD.emit_msg(0, flag, linenum(), fmt, args);
int error_char = _curchar;
char* error_ptr = _ptr+1;
@ -4515,7 +4681,7 @@ void ADLParser::next_char_or_line() {
//---------------------------next_line-----------------------------------------
void ADLParser::next_line() {
_curline = _buf.get_line(); _linenum++;
_curline = _buf.get_line();
}
//-------------------------is_literal_constant---------------------------------

View File

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

View File

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

View File

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

View File

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

View File

@ -329,6 +329,8 @@ protected:
public:
static const char *_signal; // reserved user-defined string
static const char *_signal2; // reserved user-defined string
static const char *_signal3; // reserved user-defined string
enum { Not_in_list = -1 };
void addName(const char *name);

View File

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

View File

@ -397,7 +397,7 @@ public:
void output(FILE *fp);
// --------------------------- FILE *output_routines
void print_opcode(FILE *fp, Opcode::opcode_type desired_opcode);
bool print_opcode(FILE *fp, Opcode::opcode_type desired_opcode);
};
//------------------------------InsEncode--------------------------------------
@ -779,10 +779,20 @@ public:
const char *_greater_equal;
const char *_less_equal;
const char *_greater;
const char *_equal_format;
const char *_not_equal_format;
const char *_less_format;
const char *_greater_equal_format;
const char *_less_equal_format;
const char *_greater_format;
// Public Methods
CondInterface(char *equal, char *not_equal, char *less, char *greater_equal,
char *less_equal, char *greater);
CondInterface(const char* equal, const char* equal_format,
const char* not_equal, const char* not_equal_format,
const char* less, const char* less_format,
const char* greater_equal, const char* greater_equal_format,
const char* less_equal, const char* less_equal_format,
const char* greater, const char* greater_format);
~CondInterface();
void dump();

View File

@ -1619,6 +1619,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
}
// Iterate over the new instruction's operands
int prev_pos = -1;
for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) {
// Use 'parameter' at current position in list of new instruction's formals
// instead of 'opid' when looking up info internal to new_inst
@ -1642,6 +1643,18 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
// ins = (InstructForm *) _globalNames[new_id];
exp_pos = node->operand_position_format(opid);
assert(exp_pos != -1, "Bad expand rule");
if (prev_pos > exp_pos && expand_instruction->_matrule != NULL) {
// For the add_req calls below to work correctly they need
// to added in the same order that a match would add them.
// This means that they would need to be in the order of
// the components list instead of the formal parameters.
// This is a sort of hidden invariant that previously
// wasn't checked and could lead to incorrectly
// constructed nodes.
syntax_err(node->_linenum, "For expand in %s to work, parameter declaration order in %s must follow matchrule\n",
node->_ident, new_inst->_ident);
}
prev_pos = exp_pos;
new_pos = new_inst->operand_position(parameter,Component::USE);
if (new_pos != -1) {
@ -2306,7 +2319,12 @@ private:
_processing_noninput = false;
// A replacement variable, originally '$'
if ( Opcode::as_opcode_type(rep_var) != Opcode::NOT_AN_OPCODE ) {
_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) );
if (!_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(rep_var) )) {
// Missing opcode
_AD.syntax_err( _inst._linenum,
"Missing $%s opcode definition in %s, used by encoding %s\n",
rep_var, _inst._ident, _encoding._name);
}
}
else {
// Lookup its position in parameter list
@ -2348,7 +2366,13 @@ private:
else if( Opcode::as_opcode_type(inst_rep_var) != Opcode::NOT_AN_OPCODE ) {
// else check if "primary", "secondary", "tertiary"
assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter");
_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) );
if (!_inst._opcode->print_opcode(_fp, Opcode::as_opcode_type(inst_rep_var) )) {
// Missing opcode
_AD.syntax_err( _inst._linenum,
"Missing $%s opcode definition in %s\n",
rep_var, _inst._ident);
}
_constant_status = LITERAL_OUTPUT;
}
else if((_AD.get_registers() != NULL ) && (_AD.get_registers()->getRegDef(inst_rep_var) != NULL)) {

View File

@ -355,17 +355,19 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
// ---------------------------------------------------------------------------
// Generate the format rule for condition codes
static void defineCCodeDump(FILE *fp, int i) {
fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"eq\");\n",i);
fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"ne\");\n",i);
fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"le\");\n",i);
fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"ge\");\n",i);
fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"lt\");\n",i);
fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"gt\");\n",i);
static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) {
assert(oper != NULL, "what");
CondInterface* cond = oper->_interface->is_CondInterface();
fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format);
fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format);
fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format);
}
// Output code that dumps constant values, increment "i" if type is constant
static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) {
static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) {
if (!strcmp(ideal_type, "ConI")) {
fprintf(fp," st->print(\"#%%d\", _c%d);\n", i);
++i;
@ -375,7 +377,7 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) {
++i;
}
else if (!strcmp(ideal_type, "ConN")) {
fprintf(fp," _c%d->dump();\n", i);
fprintf(fp," _c%d->dump_on(st);\n", i);
++i;
}
else if (!strcmp(ideal_type, "ConL")) {
@ -391,7 +393,7 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) {
++i;
}
else if (!strcmp(ideal_type, "Bool")) {
defineCCodeDump(fp,i);
defineCCodeDump(oper, fp,i);
++i;
}
@ -476,7 +478,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
}
// ALWAYS! Provide a special case output for condition codes.
if( oper.is_ideal_bool() ) {
defineCCodeDump(fp,0);
defineCCodeDump(&oper, fp,0);
}
fprintf(fp,"}\n");
@ -549,7 +551,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
}
// ALWAYS! Provide a special case output for condition codes.
if( oper.is_ideal_bool() ) {
defineCCodeDump(fp,0);
defineCCodeDump(&oper, fp,0);
}
fprintf(fp, "}\n");
fprintf(fp, "#endif\n");
@ -583,10 +585,53 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
while( (string = inst._format->_strings.iter()) != NULL ) {
fprintf(fp," ");
// Check if this is a standard string or a replacement variable
if( string != NameList::_signal ) // Normal string. Pass through.
if( string == NameList::_signal ) { // Replacement variable
const char* rep_var = inst._format->_rep_vars.iter();
inst.rep_var_format( fp, rep_var);
} else if( string == NameList::_signal3 ) { // Replacement variable in raw text
const char* rep_var = inst._format->_rep_vars.iter();
const Form *form = inst._localNames[rep_var];
if (form == NULL) {
fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var);
assert(false, "ShouldNotReachHere()");
}
OpClassForm *opc = form->is_opclass();
assert( opc, "replacement variable was not found in local names");
// Lookup the index position of the replacement variable
int idx = inst.operand_position_format(rep_var);
if ( idx == -1 ) {
assert( strcmp(opc->_ident,"label")==0, "Unimplemented");
assert( false, "ShouldNotReachHere()");
}
if (inst.is_noninput_operand(idx)) {
assert( false, "ShouldNotReachHere()");
} else {
// Output the format call for this operand
fprintf(fp,"opnd_array(%d)",idx);
}
rep_var = inst._format->_rep_vars.iter();
inst._format->_strings.iter();
if ( strcmp(rep_var,"$constant") == 0 && opc->is_operand()) {
Form::DataType constant_type = form->is_operand()->is_base_constant(globals);
if ( constant_type == Form::idealD ) {
fprintf(fp,"->constantD()");
} else if ( constant_type == Form::idealF ) {
fprintf(fp,"->constantF()");
} else if ( constant_type == Form::idealL ) {
fprintf(fp,"->constantL()");
} else {
fprintf(fp,"->constant()");
}
} else if ( strcmp(rep_var,"$cmpcode") == 0) {
fprintf(fp,"->ccode()");
} else {
assert( false, "ShouldNotReachHere()");
}
} else if( string == NameList::_signal2 ) // Raw program text
fputs(inst._format->_strings.iter(), fp);
else
fprintf(fp,"st->print(\"%s\");\n", string);
else // Replacement variable
inst.rep_var_format( fp, inst._format->_rep_vars.iter() );
} // Done with all format strings
} // Done generating the user-defined portion of the format
@ -1404,7 +1449,7 @@ void ArchDesc::declareClasses(FILE *fp) {
oper->_components.reset();
if ((comp = oper->_components.iter()) == NULL) {
assert(num_consts == 1, "Bad component list detected.\n");
i = dump_spec_constant( fp, type, i );
i = dump_spec_constant( fp, type, i, oper );
// Check that type actually matched
assert( i != 0, "Non-constant operand lacks component list.");
} // end if NULL
@ -1414,7 +1459,7 @@ void ArchDesc::declareClasses(FILE *fp) {
oper->_components.reset();
while((comp = oper->_components.iter()) != NULL) {
type = comp->base_type(_globalNames);
i = dump_spec_constant( fp, type, i );
i = dump_spec_constant( fp, type, i, NULL );
}
}
// finish line (3)

View File

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

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));
}
int Bytecodes::special_length_at(address bcp) {
int Bytecodes::special_length_at(address bcp, address end) {
Code code = code_at(bcp);
switch (code) {
case _wide:
if (end != NULL && bcp + 1 >= end) {
return -1; // don't read past end of code buffer
}
return wide_length_for(cast(*(bcp + 1)));
case _tableswitch:
{ address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize);
if (end != NULL && aligned_bcp + 3*jintSize >= end) {
return -1; // don't read past end of code buffer
}
jlong lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize);
jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*jintSize;
@ -73,6 +79,9 @@ int Bytecodes::special_length_at(address bcp) {
case _fast_binaryswitch: // fall through
case _fast_linearswitch:
{ address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize);
if (end != NULL && aligned_bcp + 2*jintSize >= end) {
return -1; // don't read past end of code buffer
}
jlong npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize;
// only return len if it can be represented as a positive int;
@ -90,14 +99,17 @@ int Bytecodes::special_length_at(address bcp) {
// verifier when reading in bytecode to verify. Other mechanisms that
// run at runtime (such as generateOopMaps) need to iterate over the code
// and don't expect to see breakpoints: they want to see the instruction
// which was replaces so that they can get the correct length and find
// which was replaced so that they can get the correct length and find
// the next bytecode.
int Bytecodes::raw_special_length_at(address bcp) {
//
// 'end' indicates the end of the code buffer, which we should not try to read
// past.
int Bytecodes::raw_special_length_at(address bcp, address end) {
Code code = code_or_bp_at(bcp);
if (code == _breakpoint) {
return 1;
} else {
return special_length_at(bcp);
return special_length_at(bcp, end);
}
}

View File

@ -340,8 +340,10 @@ class Bytecodes: AllStatic {
const char* wf = wide_format(code);
return (wf == NULL) ? 0 : (int)strlen(wf);
}
static int special_length_at(address bcp);
static int raw_special_length_at(address bcp);
// if 'end' is provided, it indicates the end of the code buffer which
// should not be read past when parsing.
static int special_length_at(address bcp, address end = NULL);
static int raw_special_length_at(address bcp, address end = NULL);
static int length_at (address bcp) { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
static int java_length_at (address bcp) { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; }

View File

@ -57,6 +57,14 @@ void Block_List::insert(uint i, Block *b) {
_blocks[i] = b;
}
#ifndef PRODUCT
void Block_List::print() {
for (uint i=0; i < size(); i++) {
tty->print("B%d ", _blocks[i]->_pre_order);
}
tty->print("size = %d\n", size());
}
#endif
//=============================================================================
@ -66,6 +74,12 @@ uint Block::code_alignment() {
// Check for Start block
if( _pre_order == 1 ) return InteriorEntryAlignment;
// Check for loop alignment
if (has_loop_alignment()) return loop_alignment();
return 1; // no particular alignment
}
uint Block::compute_loop_alignment() {
Node *h = head();
if( h->is_Loop() && h->as_Loop()->is_inner_loop() ) {
// Pre- and post-loops have low trip count so do not bother with
@ -83,13 +97,15 @@ uint Block::code_alignment() {
}
return OptoLoopAlignment; // Otherwise align loop head
}
return 1; // no particular alignment
}
//-----------------------------------------------------------------------------
// Compute the size of first 'inst_cnt' instructions in this block.
// Return the number of instructions left to compute if the block has
// less then 'inst_cnt' instructions.
// less then 'inst_cnt' instructions. Stop, and return 0 if sum_size
// exceeds OptoLoopAlignment.
uint Block::compute_first_inst_size(uint& sum_size, uint inst_cnt,
PhaseRegAlloc* ra) {
uint last_inst = _nodes.size();
@ -307,6 +323,8 @@ void Block::dump_head( const Block_Array *bbs ) const {
tty->print("\tLoop: B%d-B%d ", bhead->_pre_order, bx->_pre_order);
// Dump any loop-specific bits, especially for CountedLoops.
loop->dump_spec(tty);
} else if (has_loop_alignment()) {
tty->print(" top-of-loop");
}
tty->print(" Freq: %g",_freq);
if( Verbose || WizardMode ) {
@ -509,9 +527,11 @@ static bool no_flip_branch( Block *b ) {
int branch_idx = b->_nodes.size() - b->_num_succs-1;
if( branch_idx < 1 ) return false;
Node *bra = b->_nodes[branch_idx];
if( bra->is_Catch() ) return true;
if( bra->is_Catch() )
return true;
if( bra->is_Mach() ) {
if( bra->is_MachNullCheck() ) return true;
if( bra->is_MachNullCheck() )
return true;
int iop = bra->as_Mach()->ideal_Opcode();
if( iop == Op_FastLock || iop == Op_FastUnlock )
return true;
@ -557,10 +577,10 @@ void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) {
dead->_nodes[k]->del_req(j);
}
//------------------------------MoveToNext-------------------------------------
//------------------------------move_to_next-----------------------------------
// Helper function to move block bx to the slot following b_index. Return
// true if the move is successful, otherwise false
bool PhaseCFG::MoveToNext(Block* bx, uint b_index) {
bool PhaseCFG::move_to_next(Block* bx, uint b_index) {
if (bx == NULL) return false;
// Return false if bx is already scheduled.
@ -591,9 +611,9 @@ bool PhaseCFG::MoveToNext(Block* bx, uint b_index) {
return true;
}
//------------------------------MoveToEnd--------------------------------------
//------------------------------move_to_end------------------------------------
// Move empty and uncommon blocks to the end.
void PhaseCFG::MoveToEnd(Block *b, uint i) {
void PhaseCFG::move_to_end(Block *b, uint i) {
int e = b->is_Empty();
if (e != Block::not_empty) {
if (e == Block::empty_with_goto) {
@ -609,15 +629,31 @@ void PhaseCFG::MoveToEnd(Block *b, uint i) {
_blocks.push(b);
}
//------------------------------RemoveEmpty------------------------------------
// Remove empty basic blocks and useless branches.
void PhaseCFG::RemoveEmpty() {
//---------------------------set_loop_alignment--------------------------------
// Set loop alignment for every block
void PhaseCFG::set_loop_alignment() {
uint last = _num_blocks;
assert( _blocks[0] == _broot, "" );
for (uint i = 1; i < last; i++ ) {
Block *b = _blocks[i];
if (b->head()->is_Loop()) {
b->set_loop_alignment(b);
}
}
}
//-----------------------------remove_empty------------------------------------
// Make empty basic blocks to be "connector" blocks, Move uncommon blocks
// to the end.
void PhaseCFG::remove_empty() {
// Move uncommon blocks to the end
uint last = _num_blocks;
uint i;
assert( _blocks[0] == _broot, "" );
for( i = 1; i < last; i++ ) {
for (uint i = 1; i < last; i++) {
Block *b = _blocks[i];
if (b->is_connector()) break;
// Check for NeverBranch at block end. This needs to become a GOTO to the
// true target. NeverBranch are treated as a conditional branch that
@ -629,37 +665,40 @@ void PhaseCFG::RemoveEmpty() {
convert_NeverBranch_to_Goto(b);
// Look for uncommon blocks and move to end.
if( b->is_uncommon(_bbs) ) {
MoveToEnd(b, i);
last--; // No longer check for being uncommon!
if( no_flip_branch(b) ) { // Fall-thru case must follow?
b = _blocks[i]; // Find the fall-thru block
MoveToEnd(b, i);
last--;
if (!C->do_freq_based_layout()) {
if( b->is_uncommon(_bbs) ) {
move_to_end(b, i);
last--; // No longer check for being uncommon!
if( no_flip_branch(b) ) { // Fall-thru case must follow?
b = _blocks[i]; // Find the fall-thru block
move_to_end(b, i);
last--;
}
i--; // backup block counter post-increment
}
i--; // backup block counter post-increment
}
}
// Remove empty blocks
uint j1;
// Move empty blocks to the end
last = _num_blocks;
for( i=0; i < last; i++ ) {
for (uint i = 1; i < last; i++) {
Block *b = _blocks[i];
if (i > 0) {
if (b->is_Empty() != Block::not_empty) {
MoveToEnd(b, i);
last--;
i--;
}
if (b->is_Empty() != Block::not_empty) {
move_to_end(b, i);
last--;
i--;
}
} // End of for all blocks
}
//-----------------------------fixup_flow--------------------------------------
// Fix up the final control flow for basic blocks.
void PhaseCFG::fixup_flow() {
// Fixup final control flow for the blocks. Remove jump-to-next
// block. If neither arm of a IF follows the conditional branch, we
// have to add a second jump after the conditional. We place the
// TRUE branch target in succs[0] for both GOTOs and IFs.
for( i=0; i < _num_blocks; i++ ) {
for (uint i=0; i < _num_blocks; i++) {
Block *b = _blocks[i];
b->_pre_order = i; // turn pre-order into block-index
@ -700,7 +739,7 @@ void PhaseCFG::RemoveEmpty() {
}
}
// Remove all CatchProjs
for (j1 = 0; j1 < b->_num_succs; j1++) b->_nodes.pop();
for (uint j1 = 0; j1 < b->_num_succs; j1++) b->_nodes.pop();
} else if (b->_num_succs == 1) {
// Block ends in a Goto?
@ -730,8 +769,7 @@ void PhaseCFG::RemoveEmpty() {
// successors after the current one, provided that the
// successor was previously unscheduled, but moveable
// (i.e., all paths to it involve a branch).
if( bnext != bs0 && bnext != bs1 ) {
if( !C->do_freq_based_layout() && bnext != bs0 && bnext != bs1 ) {
// Choose the more common successor based on the probability
// of the conditional branch.
Block *bx = bs0;
@ -751,9 +789,9 @@ void PhaseCFG::RemoveEmpty() {
}
// Attempt the more common successor first
if (MoveToNext(bx, i)) {
if (move_to_next(bx, i)) {
bnext = bx;
} else if (MoveToNext(by, i)) {
} else if (move_to_next(by, i)) {
bnext = by;
}
}
@ -774,10 +812,8 @@ void PhaseCFG::RemoveEmpty() {
// Flip projection for each target
{ ProjNode *tmp = proj0; proj0 = proj1; proj1 = tmp; }
} else if( bnext == bs1 ) { // Fall-thru is already in succs[1]
} else { // Else need a double-branch
} else if( bnext != bs1 ) {
// Need a double-branch
// The existing conditional branch need not change.
// Add a unconditional branch to the false target.
// Alas, it must appear in its own block and adding a
@ -786,8 +822,9 @@ void PhaseCFG::RemoveEmpty() {
}
// Make sure we TRUE branch to the target
if( proj0->Opcode() == Op_IfFalse )
if( proj0->Opcode() == Op_IfFalse ) {
iff->negate();
}
b->_nodes.pop(); // Remove IfFalse & IfTrue projections
b->_nodes.pop();
@ -796,9 +833,7 @@ void PhaseCFG::RemoveEmpty() {
// Multi-exit block, e.g. a switch statement
// But we don't need to do anything here
}
} // End of for all blocks
}
@ -905,7 +940,7 @@ void UnionFind::reset( uint max ) {
// Force the Union-Find mapping to be at least this large
extend(max,0);
// Initialize to be the ID mapping.
for( uint i=0; i<_max; i++ ) map(i,i);
for( uint i=0; i<max; i++ ) map(i,i);
}
//------------------------------Find_compress----------------------------------
@ -937,7 +972,6 @@ uint UnionFind::Find_const( uint idx ) const {
if( idx >= _max ) return idx;
uint next = lookup(idx);
while( next != idx ) { // Scan chain of equivalences
assert( next < idx, "always union smaller" );
idx = next; // until find a fixed-point
next = lookup(idx);
}
@ -956,3 +990,491 @@ void UnionFind::Union( uint idx1, uint idx2 ) {
assert( src < dst, "always union smaller" );
map(dst,src);
}
#ifndef PRODUCT
static void edge_dump(GrowableArray<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 );
uint size() const { return _cnt; }
void reset() { _cnt = 0; }
void print();
};
@ -129,7 +130,11 @@ class Block : public CFGElement {
uint _rpo; // Number in reverse post order walk
virtual bool is_block() { return true; }
float succ_prob(uint i); // return probability of i'th successor
float succ_prob(uint i); // return probability of i'th successor
int num_fall_throughs(); // How many fall-through candidate this block has
void update_uncommon_branch(Block* un); // Lower branch prob to uncommon code
bool succ_fall_through(uint i); // Is successor "i" is a fall-through candidate
Block* lone_fall_through(); // Return lone fall-through Block or null
Block* dom_lca(Block* that); // Compute LCA in dominator tree.
#ifdef ASSERT
@ -144,6 +149,7 @@ class Block : public CFGElement {
// Report the alignment required by this block. Must be a power of 2.
// The previous block will insert nops to get this alignment.
uint code_alignment();
uint compute_loop_alignment();
// BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies.
// It is currently also used to scale such frequencies relative to
@ -184,11 +190,12 @@ class Block : public CFGElement {
int current_alignment = current_offset & max_pad;
if( current_alignment != 0 ) {
uint padding = (block_alignment-current_alignment) & max_pad;
if( !head()->is_Loop() ||
padding <= (uint)MaxLoopPad ||
first_inst_size() > padding ) {
return padding;
if( has_loop_alignment() &&
padding > (uint)MaxLoopPad &&
first_inst_size() <= padding ) {
return 0;
}
return padding;
}
}
return 0;
@ -202,6 +209,21 @@ class Block : public CFGElement {
void set_connector() { _connector = true; }
bool is_connector() const { return _connector; };
// Loop_alignment will be set for blocks which are at the top of loops.
// The block layout pass may rotate loops such that the loop head may not
// be the sequentially first block of the loop encountered in the linear
// list of blocks. If the layout pass is not run, loop alignment is set
// for each block which is the head of a loop.
uint _loop_alignment;
void set_loop_alignment(Block *loop_top) {
uint new_alignment = loop_top->compute_loop_alignment();
if (new_alignment > _loop_alignment) {
_loop_alignment = new_alignment;
}
}
uint loop_alignment() const { return _loop_alignment; }
bool has_loop_alignment() const { return loop_alignment() > 0; }
// Create a new Block with given head Node.
// Creates the (empty) predecessor arrays.
Block( Arena *a, Node *headnode )
@ -219,7 +241,8 @@ class Block : public CFGElement {
_raise_LCA_mark(0),
_raise_LCA_visited(0),
_first_inst_size(999999),
_connector(false) {
_connector(false),
_loop_alignment(0) {
_nodes.push(headnode);
}
@ -275,6 +298,16 @@ class Block : public CFGElement {
return s;
}
// Return true if b is a successor of this block
bool has_successor(Block* b) const {
for (uint i = 0; i < _num_succs; i++ ) {
if (non_connector_successor(i) == b) {
return true;
}
}
return false;
}
// Successor block, after forwarding through connectors
Block* non_connector_successor(int i) const {
return _succs[i]->non_connector();
@ -319,7 +352,6 @@ class PhaseCFG : public Phase {
// I'll need a few machine-specific GotoNodes. Clone from this one.
MachNode *_goto;
void insert_goto_at(uint block_no, uint succ_no);
Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false);
void verify_anti_dependences(Block* LCA, Node* load) {
@ -379,10 +411,15 @@ class PhaseCFG : public Phase {
// Compute the instruction global latency with a backwards walk
void ComputeLatenciesBackwards(VectorSet &visited, Node_List &stack);
// Set loop alignment
void set_loop_alignment();
// Remove empty basic blocks
void RemoveEmpty();
bool MoveToNext(Block* bx, uint b_index);
void MoveToEnd(Block* bx, uint b_index);
void remove_empty();
void fixup_flow();
bool move_to_next(Block* bx, uint b_index);
void move_to_end(Block* bx, uint b_index);
void insert_goto_at(uint block_no, uint succ_no);
// Check for NeverBranch at block end. This needs to become a GOTO to the
// true target. NeverBranch are treated as a conditional branch that always
@ -413,7 +450,7 @@ class PhaseCFG : public Phase {
};
//------------------------------UnionFindInfo----------------------------------
//------------------------------UnionFind--------------------------------------
// Map Block indices to a block-index for a cfg-cover.
// Array lookup in the optimized case.
class UnionFind : public ResourceObj {
@ -508,3 +545,166 @@ class CFGLoop : public CFGElement {
void dump_tree() const;
#endif
};
//----------------------------------CFGEdge------------------------------------
// A edge between two basic blocks that will be embodied by a branch or a
// fall-through.
class CFGEdge : public ResourceObj {
private:
Block * _from; // Source basic block
Block * _to; // Destination basic block
float _freq; // Execution frequency (estimate)
int _state;
bool _infrequent;
int _from_pct;
int _to_pct;
// Private accessors
int from_pct() const { return _from_pct; }
int to_pct() const { return _to_pct; }
int from_infrequent() const { return from_pct() < BlockLayoutMinDiamondPercentage; }
int to_infrequent() const { return to_pct() < BlockLayoutMinDiamondPercentage; }
public:
enum {
open, // initial edge state; unprocessed
connected, // edge used to connect two traces together
interior // edge is interior to trace (could be backedge)
};
CFGEdge(Block *from, Block *to, float freq, int from_pct, int to_pct) :
_from(from), _to(to), _freq(freq),
_from_pct(from_pct), _to_pct(to_pct), _state(open) {
_infrequent = from_infrequent() || to_infrequent();
}
float freq() const { return _freq; }
Block* from() const { return _from; }
Block* to () const { return _to; }
int infrequent() const { return _infrequent; }
int state() const { return _state; }
void set_state(int state) { _state = state; }
#ifndef PRODUCT
void dump( ) const;
#endif
};
//-----------------------------------Trace-------------------------------------
// An ordered list of basic blocks.
class Trace : public ResourceObj {
private:
uint _id; // Unique Trace id (derived from initial block)
Block ** _next_list; // Array mapping index to next block
Block ** _prev_list; // Array mapping index to previous block
Block * _first; // First block in the trace
Block * _last; // Last block in the trace
// Return the block that follows "b" in the trace.
Block * next(Block *b) const { return _next_list[b->_pre_order]; }
void set_next(Block *b, Block *n) const { _next_list[b->_pre_order] = n; }
// Return the block that preceeds "b" in the trace.
Block * prev(Block *b) const { return _prev_list[b->_pre_order]; }
void set_prev(Block *b, Block *p) const { _prev_list[b->_pre_order] = p; }
// We've discovered a loop in this trace. Reset last to be "b", and first as
// the block following "b
void break_loop_after(Block *b) {
_last = b;
_first = next(b);
set_prev(_first, NULL);
set_next(_last, NULL);
}
public:
Trace(Block *b, Block **next_list, Block **prev_list) :
_first(b),
_last(b),
_next_list(next_list),
_prev_list(prev_list),
_id(b->_pre_order) {
set_next(b, NULL);
set_prev(b, NULL);
};
// Return the id number
uint id() const { return _id; }
void set_id(uint id) { _id = id; }
// Return the first block in the trace
Block * first_block() const { return _first; }
// Return the last block in the trace
Block * last_block() const { return _last; }
// Insert a trace in the middle of this one after b
void insert_after(Block *b, Trace *tr) {
set_next(tr->last_block(), next(b));
if (next(b) != NULL) {
set_prev(next(b), tr->last_block());
}
set_next(b, tr->first_block());
set_prev(tr->first_block(), b);
if (b == _last) {
_last = tr->last_block();
}
}
void insert_before(Block *b, Trace *tr) {
Block *p = prev(b);
assert(p != NULL, "use append instead");
insert_after(p, tr);
}
// Append another trace to this one.
void append(Trace *tr) {
insert_after(_last, tr);
}
// Append a block at the end of this trace
void append(Block *b) {
set_next(_last, b);
set_prev(b, _last);
_last = b;
}
// Adjust the the blocks in this trace
void fixup_blocks(PhaseCFG &cfg);
bool backedge(CFGEdge *e);
#ifndef PRODUCT
void dump( ) const;
#endif
};
//------------------------------PhaseBlockLayout-------------------------------
// Rearrange blocks into some canonical order, based on edges and their frequencies
class PhaseBlockLayout : public Phase {
PhaseCFG &_cfg; // Control flow graph
GrowableArray<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, \
"Array size (number of elements) limit for scalar replacement") \
\
product(bool, UseOptoBiasInlining, true, \
"Generate biased locking code in C2 ideal graph") \
\
product(intx, ValueSearchLimit, 1000, \
"Recursion limit in PhaseMacroExpand::value_from_mem_phi") \
\
@ -396,5 +399,15 @@
\
diagnostic(intx, DominatorSearchLimit, 1000, \
"Iterations limit in Node::dominates") \
\
product(bool, BlockLayoutByFrequency, true, \
"Use edge frequencies to drive block ordering") \
\
product(intx, BlockLayoutMinDiamondPercentage, 20, \
"Miniumum %% of a successor (predecessor) for which block layout "\
"a will allow a fork (join) in a single chain") \
\
product(bool, BlockLayoutRotateLoops, false, \
"Allow back branches to be fall throughs in the block layour") \
C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)

View File

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

View File

@ -433,6 +433,10 @@ public:
uint n_fields() const { return _n_fields; }
DEBUG_ONLY(AllocateNode* alloc() const { return _alloc; })
// SafePointScalarObject should be always pinned to the control edge
// of the SafePoint node for which it was generated.
virtual bool pinned() const; // { return true; }
virtual uint size_of() const { return sizeof(*this); }
// Assumes that "this" is an argument to a safepoint node "s", and that

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");
// This frame must preserve the required fp alignment
const int stack_alignment_in_words = Matcher::stack_alignment_in_slots();
if (stack_alignment_in_words > 0)
_framesize = round_to(_framesize, Matcher::stack_alignment_in_bytes());
_framesize = round_to(_framesize, Matcher::stack_alignment_in_slots());
assert( _framesize >= 0 && _framesize <= 1000000, "sanity check" );
#ifndef PRODUCT
_total_framesize += _framesize;

View File

@ -205,6 +205,7 @@ macro(StoreB)
macro(StoreC)
macro(StoreCM)
macro(StorePConditional)
macro(StoreIConditional)
macro(StoreLConditional)
macro(StoreD)
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());
}
print_method("Before RemoveUseless");
print_method("Before RemoveUseless", 3);
// Remove clutter produced by parsing.
if (!failing()) {
@ -822,6 +822,7 @@ void Compile::Init(int aliaslevel) {
Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
set_decompile_count(0);
set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
// Compilation level related initialization
if (env()->comp_level() == CompLevel_fast_compile) {
set_num_loop_opts(Tier1LoopOptsCount);
@ -1701,8 +1702,14 @@ void Compile::Code_Gen() {
// are not adding any new instructions. If any basic block is empty, we
// can now safely remove it.
{
NOT_PRODUCT( TracePhase t2("removeEmpty", &_t_removeEmptyBlocks, TimeCompiler); )
cfg.RemoveEmpty();
NOT_PRODUCT( TracePhase t2("blockOrdering", &_t_blockOrdering, TimeCompiler); )
cfg.remove_empty();
if (do_freq_based_layout()) {
PhaseBlockLayout layout(cfg);
} else {
cfg.set_loop_alignment();
}
cfg.fixup_flow();
}
// Perform any platform dependent postallocation verifications.
@ -1994,6 +2001,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
case Op_StorePConditional:
case Op_StoreI:
case Op_StoreL:
case Op_StoreIConditional:
case Op_StoreLConditional:
case Op_CompareAndSwapI:
case Op_CompareAndSwapL:

View File

@ -154,6 +154,7 @@ class Compile : public Phase {
uint _decompile_count; // Cumulative decompilation counts.
bool _do_inlining; // True if we intend to do inlining
bool _do_scheduling; // True if we intend to do scheduling
bool _do_freq_based_layout; // True if we intend to do frequency based block layout
bool _do_count_invocations; // True if we generate code to count invocations
bool _do_method_data_update; // True if we generate code to update methodDataOops
int _AliasLevel; // Locally-adjusted version of AliasLevel flag.
@ -307,6 +308,8 @@ class Compile : public Phase {
void set_do_inlining(bool z) { _do_inlining = z; }
bool do_scheduling() const { return _do_scheduling; }
void set_do_scheduling(bool z) { _do_scheduling = z; }
bool do_freq_based_layout() const{ return _do_freq_based_layout; }
void set_do_freq_based_layout(bool z){ _do_freq_based_layout = z; }
bool do_count_invocations() const{ return _do_count_invocations; }
void set_do_count_invocations(bool z){ _do_count_invocations = z; }
bool do_method_data_update() const { return _do_method_data_update; }

View File

@ -1319,11 +1319,33 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_
//------------------------------Estimate_Block_Frequency-----------------------
// Estimate block frequencies based on IfNode probabilities.
void PhaseCFG::Estimate_Block_Frequency() {
int cnts = C->method() ? C->method()->interpreter_invocation_count() : 1;
// Most of our algorithms will die horribly if frequency can become
// negative so make sure cnts is a sane value.
if( cnts <= 0 ) cnts = 1;
float f = (float)cnts/(float)FreqCountInvocations;
// Force conditional branches leading to uncommon traps to be unlikely,
// not because we get to the uncommon_trap with less relative frequency,
// but because an uncommon_trap typically causes a deopt, so we only get
// there once.
if (C->do_freq_based_layout()) {
Block_List worklist;
Block* root_blk = _blocks[0];
for (uint i = 1; i < root_blk->num_preds(); i++) {
Block *pb = _bbs[root_blk->pred(i)->_idx];
if (pb->has_uncommon_code()) {
worklist.push(pb);
}
}
while (worklist.size() > 0) {
Block* uct = worklist.pop();
if (uct == _broot) continue;
for (uint i = 1; i < uct->num_preds(); i++) {
Block *pb = _bbs[uct->pred(i)->_idx];
if (pb->_num_succs == 1) {
worklist.push(pb);
} else if (pb->num_fall_throughs() == 2) {
pb->update_uncommon_branch(uct);
}
}
}
}
// Create the loop tree and calculate loop depth.
_root_loop = create_loop_tree();
@ -1333,27 +1355,29 @@ void PhaseCFG::Estimate_Block_Frequency() {
_root_loop->compute_freq();
// Adjust all frequencies to be relative to a single method entry
_root_loop->_freq = f * 1.0;
_root_loop->_freq = 1.0;
_root_loop->scale_freq();
// force paths ending at uncommon traps to be infrequent
Block_List worklist;
Block* root_blk = _blocks[0];
for (uint i = 0; i < root_blk->num_preds(); i++) {
Block *pb = _bbs[root_blk->pred(i)->_idx];
if (pb->has_uncommon_code()) {
worklist.push(pb);
}
}
while (worklist.size() > 0) {
Block* uct = worklist.pop();
uct->_freq = PROB_MIN;
for (uint i = 0; i < uct->num_preds(); i++) {
Block *pb = _bbs[uct->pred(i)->_idx];
if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) {
if (!C->do_freq_based_layout()) {
Block_List worklist;
Block* root_blk = _blocks[0];
for (uint i = 1; i < root_blk->num_preds(); i++) {
Block *pb = _bbs[root_blk->pred(i)->_idx];
if (pb->has_uncommon_code()) {
worklist.push(pb);
}
}
while (worklist.size() > 0) {
Block* uct = worklist.pop();
uct->_freq = PROB_MIN;
for (uint i = 1; i < uct->num_preds(); i++) {
Block *pb = _bbs[uct->pred(i)->_idx];
if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) {
worklist.push(pb);
}
}
}
}
#ifndef PRODUCT
@ -1556,22 +1580,6 @@ void CFGLoop::compute_freq() {
}
}
#if 0
// Raise frequency of the loop backedge block, in an effort
// to keep it empty. Skip the method level "loop".
if (_parent != NULL) {
CFGElement* s = _members.at(_members.length() - 1);
if (s->is_block()) {
Block* bk = s->as_Block();
if (bk->_num_succs == 1 && bk->_succs[0] == hd) {
// almost any value >= 1.0f works
// FIXME: raw constant
bk->_freq = 1.05f;
}
}
}
#endif
// For all loops other than the outer, "method" loop,
// sum and normalize the exit probability. The "method" loop
// should keep the initial exit probability of 1, so that
@ -1589,12 +1597,15 @@ void CFGLoop::compute_freq() {
// the probability of exit per loop entry.
for (int i = 0; i < _exits.length(); i++) {
Block* et = _exits.at(i).get_target();
float new_prob = _exits.at(i).get_prob() / exits_sum;
float new_prob = 0.0f;
if (_exits.at(i).get_prob() > 0.0f) {
new_prob = _exits.at(i).get_prob() / exits_sum;
}
BlockProbPair bpp(et, new_prob);
_exits.at_put(i, bpp);
}
// Save the total, but guard against unreasoable probability,
// Save the total, but guard against unreasonable probability,
// as the value is used to estimate the loop trip count.
// An infinite trip count would blur relative block
// frequencies.
@ -1688,6 +1699,137 @@ float Block::succ_prob(uint i) {
return 0.0f;
}
//------------------------------num_fall_throughs-----------------------------
// Return the number of fall-through candidates for a block
int Block::num_fall_throughs() {
int eidx = end_idx();
Node *n = _nodes[eidx]; // Get ending Node
int op = n->Opcode();
if (n->is_Mach()) {
if (n->is_MachNullCheck()) {
// In theory, either side can fall-thru, for simplicity sake,
// let's say only the false branch can now.
return 1;
}
op = n->as_Mach()->ideal_Opcode();
}
// Switch on branch type
switch( op ) {
case Op_CountedLoopEnd:
case Op_If:
return 2;
case Op_Root:
case Op_Goto:
return 1;
case Op_Catch: {
for (uint i = 0; i < _num_succs; i++) {
const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj();
if (ci->_con == CatchProjNode::fall_through_index) {
return 1;
}
}
return 0;
}
case Op_Jump:
case Op_NeverBranch:
case Op_TailCall:
case Op_TailJump:
case Op_Return:
case Op_Halt:
case Op_Rethrow:
return 0;
default:
ShouldNotReachHere();
}
return 0;
}
//------------------------------succ_fall_through-----------------------------
// Return true if a specific successor could be fall-through target.
bool Block::succ_fall_through(uint i) {
int eidx = end_idx();
Node *n = _nodes[eidx]; // Get ending Node
int op = n->Opcode();
if (n->is_Mach()) {
if (n->is_MachNullCheck()) {
// In theory, either side can fall-thru, for simplicity sake,
// let's say only the false branch can now.
return _nodes[i + eidx + 1]->Opcode() == Op_IfFalse;
}
op = n->as_Mach()->ideal_Opcode();
}
// Switch on branch type
switch( op ) {
case Op_CountedLoopEnd:
case Op_If:
case Op_Root:
case Op_Goto:
return true;
case Op_Catch: {
const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj();
return ci->_con == CatchProjNode::fall_through_index;
}
case Op_Jump:
case Op_NeverBranch:
case Op_TailCall:
case Op_TailJump:
case Op_Return:
case Op_Halt:
case Op_Rethrow:
return false;
default:
ShouldNotReachHere();
}
return false;
}
//------------------------------update_uncommon_branch------------------------
// Update the probability of a two-branch to be uncommon
void Block::update_uncommon_branch(Block* ub) {
int eidx = end_idx();
Node *n = _nodes[eidx]; // Get ending Node
int op = n->as_Mach()->ideal_Opcode();
assert(op == Op_CountedLoopEnd || op == Op_If, "must be a If");
assert(num_fall_throughs() == 2, "must be a two way branch block");
// Which successor is ub?
uint s;
for (s = 0; s <_num_succs; s++) {
if (_succs[s] == ub) break;
}
assert(s < 2, "uncommon successor must be found");
// If ub is the true path, make the proability small, else
// ub is the false path, and make the probability large
bool invert = (_nodes[s + eidx + 1]->Opcode() == Op_IfFalse);
// Get existing probability
float p = n->as_MachIf()->_prob;
if (invert) p = 1.0 - p;
if (p > PROB_MIN) {
p = PROB_MIN;
}
if (invert) p = 1.0 - p;
n->as_MachIf()->_prob = p;
}
//------------------------------update_succ_freq-------------------------------
// Update the appropriate frequency associated with block 'b', a succesor of
// a block in this loop.

View File

@ -3485,11 +3485,32 @@ bool LibraryCallKit::inline_native_AtomicLong_attemptUpdate() {
const TypePtr *adr_type = _gvn.type(adr)->is_ptr();
int alias_idx = C->get_alias_index(adr_type);
Node *result = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal));
Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(result));
Node *cas = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal));
Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(cas));
set_memory(store_proj, alias_idx);
Node *bol = _gvn.transform( new (C, 2) BoolNode( cas, BoolTest::eq ) );
push(result);
Node *result;
// CMove node is not used to be able fold a possible check code
// after attemptUpdate() call. This code could be transformed
// into CMove node by loop optimizations.
{
RegionNode *r = new (C, 3) RegionNode(3);
result = new (C, 3) PhiNode(r, TypeInt::BOOL);
Node *iff = create_and_xform_if(control(), bol, PROB_FAIR, COUNT_UNKNOWN);
Node *iftrue = opt_iff(r, iff);
r->init_req(1, iftrue);
result->init_req(1, intcon(1));
result->init_req(2, intcon(0));
set_control(_gvn.transform(r));
record_for_igvn(r);
C->set_has_split_ifs(true); // Has chance for split-if optimization
}
push(_gvn.transform(result));
return true;
}

View File

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

View File

@ -82,16 +82,31 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal
}
}
Node* PhaseMacroExpand::opt_iff(Node* region, Node* iff) {
IfNode *opt_iff = transform_later(iff)->as_If();
Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) {
Node* cmp;
if (mask != 0) {
Node* and_node = transform_later(new (C, 3) AndXNode(word, MakeConX(mask)));
cmp = transform_later(new (C, 3) CmpXNode(and_node, MakeConX(bits)));
} else {
cmp = word;
}
Node* bol = transform_later(new (C, 2) BoolNode(cmp, BoolTest::ne));
IfNode* iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
transform_later(iff);
// Fast path taken; set region slot 2
Node *fast_taken = transform_later( new (C, 1) IfFalseNode(opt_iff) );
region->init_req(2,fast_taken); // Capture fast-control
// Fast path taken.
Node *fast_taken = transform_later( new (C, 1) IfFalseNode(iff) );
// Fast path not-taken, i.e. slow path
Node *slow_taken = transform_later( new (C, 1) IfTrueNode(opt_iff) );
return slow_taken;
Node *slow_taken = transform_later( new (C, 1) IfTrueNode(iff) );
if (return_fast_path) {
region->init_req(edge, slow_taken); // Capture slow-control
return fast_taken;
} else {
region->init_req(edge, fast_taken); // Capture fast-control
return slow_taken;
}
}
//--------------------copy_predefined_input_for_runtime_call--------------------
@ -854,7 +869,7 @@ void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_ad
Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) {
Node* adr = basic_plus_adr(base, offset);
const TypePtr* adr_type = TypeRawPtr::BOTTOM;
const TypePtr* adr_type = adr->bottom_type()->is_ptr();
Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt);
transform_later(value);
return value;
@ -1583,12 +1598,194 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
Node* flock = lock->fastlock_node();
// Make the merge point
Node *region = new (C, 3) RegionNode(3);
Node *region;
Node *mem_phi;
Node *slow_path;
Node *bol = transform_later(new (C, 2) BoolNode(flock,BoolTest::ne));
Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
// Optimize test; set region slot 2
Node *slow_path = opt_iff(region,iff);
if (UseOptoBiasInlining) {
/*
* See the full descrition in MacroAssembler::biased_locking_enter().
*
* if( (mark_word & biased_lock_mask) == biased_lock_pattern ) {
* // The object is biased.
* proto_node = klass->prototype_header;
* o_node = thread | proto_node;
* x_node = o_node ^ mark_word;
* if( (x_node & ~age_mask) == 0 ) { // Biased to the current thread ?
* // Done.
* } else {
* if( (x_node & biased_lock_mask) != 0 ) {
* // The klass's prototype header is no longer biased.
* cas(&mark_word, mark_word, proto_node)
* goto cas_lock;
* } else {
* // The klass's prototype header is still biased.
* if( (x_node & epoch_mask) != 0 ) { // Expired epoch?
* old = mark_word;
* new = o_node;
* } else {
* // Different thread or anonymous biased.
* old = mark_word & (epoch_mask | age_mask | biased_lock_mask);
* new = thread | old;
* }
* // Try to rebias.
* if( cas(&mark_word, old, new) == 0 ) {
* // Done.
* } else {
* goto slow_path; // Failed.
* }
* }
* }
* } else {
* // The object is not biased.
* cas_lock:
* if( FastLock(obj) == 0 ) {
* // Done.
* } else {
* slow_path:
* OptoRuntime::complete_monitor_locking_Java(obj);
* }
* }
*/
region = new (C, 5) RegionNode(5);
// create a Phi for the memory state
mem_phi = new (C, 5) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
Node* fast_lock_region = new (C, 3) RegionNode(3);
Node* fast_lock_mem_phi = new (C, 3) PhiNode( fast_lock_region, Type::MEMORY, TypeRawPtr::BOTTOM);
// First, check mark word for the biased lock pattern.
Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type());
// Get fast path - mark word has the biased lock pattern.
ctrl = opt_bits_test(ctrl, fast_lock_region, 1, mark_node,
markOopDesc::biased_lock_mask_in_place,
markOopDesc::biased_lock_pattern, true);
// fast_lock_region->in(1) is set to slow path.
fast_lock_mem_phi->init_req(1, mem);
// Now check that the lock is biased to the current thread and has
// the same epoch and bias as Klass::_prototype_header.
// Special-case a fresh allocation to avoid building nodes:
Node* klass_node = AllocateNode::Ideal_klass(obj, &_igvn);
if (klass_node == NULL) {
Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) );
klass_node->init_req(0, ctrl);
}
Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type());
Node* thread = transform_later(new (C, 1) ThreadLocalNode());
Node* cast_thread = transform_later(new (C, 2) CastP2XNode(ctrl, thread));
Node* o_node = transform_later(new (C, 3) OrXNode(cast_thread, proto_node));
Node* x_node = transform_later(new (C, 3) XorXNode(o_node, mark_node));
// Get slow path - mark word does NOT match the value.
Node* not_biased_ctrl = opt_bits_test(ctrl, region, 3, x_node,
(~markOopDesc::age_mask_in_place), 0);
// region->in(3) is set to fast path - the object is biased to the current thread.
mem_phi->init_req(3, mem);
// Mark word does NOT match the value (thread | Klass::_prototype_header).
// First, check biased pattern.
// Get fast path - _prototype_header has the same biased lock pattern.
ctrl = opt_bits_test(not_biased_ctrl, fast_lock_region, 2, x_node,
markOopDesc::biased_lock_mask_in_place, 0, true);
not_biased_ctrl = fast_lock_region->in(2); // Slow path
// fast_lock_region->in(2) - the prototype header is no longer biased
// and we have to revoke the bias on this object.
// We are going to try to reset the mark of this object to the prototype
// value and fall through to the CAS-based locking scheme.
Node* adr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
Node* cas = new (C, 5) StoreXConditionalNode(not_biased_ctrl, mem, adr,
proto_node, mark_node);
transform_later(cas);
Node* proj = transform_later( new (C, 1) SCMemProjNode(cas));
fast_lock_mem_phi->init_req(2, proj);
// Second, check epoch bits.
Node* rebiased_region = new (C, 3) RegionNode(3);
Node* old_phi = new (C, 3) PhiNode( rebiased_region, TypeX_X);
Node* new_phi = new (C, 3) PhiNode( rebiased_region, TypeX_X);
// Get slow path - mark word does NOT match epoch bits.
Node* epoch_ctrl = opt_bits_test(ctrl, rebiased_region, 1, x_node,
markOopDesc::epoch_mask_in_place, 0);
// The epoch of the current bias is not valid, attempt to rebias the object
// toward the current thread.
rebiased_region->init_req(2, epoch_ctrl);
old_phi->init_req(2, mark_node);
new_phi->init_req(2, o_node);
// rebiased_region->in(1) is set to fast path.
// The epoch of the current bias is still valid but we know
// nothing about the owner; it might be set or it might be clear.
Node* cmask = MakeConX(markOopDesc::biased_lock_mask_in_place |
markOopDesc::age_mask_in_place |
markOopDesc::epoch_mask_in_place);
Node* old = transform_later(new (C, 3) AndXNode(mark_node, cmask));
cast_thread = transform_later(new (C, 2) CastP2XNode(ctrl, thread));
Node* new_mark = transform_later(new (C, 3) OrXNode(cast_thread, old));
old_phi->init_req(1, old);
new_phi->init_req(1, new_mark);
transform_later(rebiased_region);
transform_later(old_phi);
transform_later(new_phi);
// Try to acquire the bias of the object using an atomic operation.
// If this fails we will go in to the runtime to revoke the object's bias.
cas = new (C, 5) StoreXConditionalNode(rebiased_region, mem, adr,
new_phi, old_phi);
transform_later(cas);
proj = transform_later( new (C, 1) SCMemProjNode(cas));
// Get slow path - Failed to CAS.
not_biased_ctrl = opt_bits_test(rebiased_region, region, 4, cas, 0, 0);
mem_phi->init_req(4, proj);
// region->in(4) is set to fast path - the object is rebiased to the current thread.
// Failed to CAS.
slow_path = new (C, 3) RegionNode(3);
Node *slow_mem = new (C, 3) PhiNode( slow_path, Type::MEMORY, TypeRawPtr::BOTTOM);
slow_path->init_req(1, not_biased_ctrl); // Capture slow-control
slow_mem->init_req(1, proj);
// Call CAS-based locking scheme (FastLock node).
transform_later(fast_lock_region);
transform_later(fast_lock_mem_phi);
// Get slow path - FastLock failed to lock the object.
ctrl = opt_bits_test(fast_lock_region, region, 2, flock, 0, 0);
mem_phi->init_req(2, fast_lock_mem_phi);
// region->in(2) is set to fast path - the object is locked to the current thread.
slow_path->init_req(2, ctrl); // Capture slow-control
slow_mem->init_req(2, fast_lock_mem_phi);
transform_later(slow_path);
transform_later(slow_mem);
// Reset lock's memory edge.
lock->set_req(TypeFunc::Memory, slow_mem);
} else {
region = new (C, 3) RegionNode(3);
// create a Phi for the memory state
mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
// Optimize test; set region slot 2
slow_path = opt_bits_test(ctrl, region, 2, flock, 0, 0);
mem_phi->init_req(2, mem);
}
// Make slow path call
CallNode *call = make_slow_call( (CallNode *) lock, OptoRuntime::complete_monitor_enter_Type(), OptoRuntime::complete_monitor_locking_Java(), NULL, slow_path, obj, box );
@ -1614,16 +1811,11 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
transform_later(region);
_igvn.subsume_node(_fallthroughproj, region);
// create a Phi for the memory state
Node *mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
Node *memproj = transform_later( new (C, 1) ProjNode(call, TypeFunc::Memory) );
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
mem_phi->init_req(1, memproj );
mem_phi->init_req(2, mem);
transform_later(mem_phi);
_igvn.hash_delete(_memproj_fallthrough);
_igvn.hash_delete(_memproj_fallthrough);
_igvn.subsume_node(_memproj_fallthrough, mem_phi);
}
//------------------------------expand_unlock_node----------------------
@ -1637,14 +1829,31 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
// No need for a null check on unlock
// Make the merge point
RegionNode *region = new (C, 3) RegionNode(3);
Node *region;
Node *mem_phi;
if (UseOptoBiasInlining) {
// Check for biased locking unlock case, which is a no-op.
// See the full descrition in MacroAssembler::biased_locking_exit().
region = new (C, 4) RegionNode(4);
// create a Phi for the memory state
mem_phi = new (C, 4) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
mem_phi->init_req(3, mem);
Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type());
ctrl = opt_bits_test(ctrl, region, 3, mark_node,
markOopDesc::biased_lock_mask_in_place,
markOopDesc::biased_lock_pattern);
} else {
region = new (C, 3) RegionNode(3);
// create a Phi for the memory state
mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
}
FastUnlockNode *funlock = new (C, 3) FastUnlockNode( ctrl, obj, box );
funlock = transform_later( funlock )->as_FastUnlock();
Node *bol = transform_later(new (C, 2) BoolNode(funlock,BoolTest::ne));
Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
// Optimize test; set region slot 2
Node *slow_path = opt_iff(region,iff);
Node *slow_path = opt_bits_test(ctrl, region, 2, funlock, 0, 0);
CallNode *call = make_slow_call( (CallNode *) unlock, OptoRuntime::complete_monitor_exit_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), "complete_monitor_unlocking_C", slow_path, obj, box );
@ -1666,16 +1875,12 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
transform_later(region);
_igvn.subsume_node(_fallthroughproj, region);
// create a Phi for the memory state
Node *mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
mem_phi->init_req(1, memproj );
mem_phi->init_req(2, mem);
transform_later(mem_phi);
_igvn.hash_delete(_memproj_fallthrough);
_igvn.hash_delete(_memproj_fallthrough);
_igvn.subsume_node(_memproj_fallthrough, mem_phi);
}
//------------------------------expand_macro_nodes----------------------

View File

@ -93,7 +93,7 @@ private:
int replace_input(Node *use, Node *oldref, Node *newref);
void copy_call_debug_info(CallNode *oldcall, CallNode * newcall);
Node* opt_iff(Node* region, Node* iff);
Node* opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path = false);
void copy_predefined_input_for_runtime_call(Node * ctrl, CallNode* oldcall, CallNode* call);
CallNode* make_slow_call(CallNode *oldcall, const TypeFunc* slow_call_type, address slow_call,
const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1);

View File

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

View File

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

View File

@ -227,6 +227,14 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
const Type *t_adr = phase->type( address );
if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL
PhaseIterGVN *igvn = phase->is_IterGVN();
if( can_reshape && igvn != NULL && igvn->_worklist.member(address) ) {
// The address's base and type may change when the address is processed.
// Delay this mem node transformation until the address is processed.
phase->is_IterGVN()->_worklist.push(this);
return NodeSentinel; // caller will return NULL
}
// Avoid independent memory operations
Node* old_mem = mem;

View File

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

View File

@ -263,7 +263,7 @@ bool Compile::is_node_getting_a_safepoint( Node* n) {
# endif // ENABLE_ZAP_DEAD_LOCALS
//------------------------------compute_loop_first_inst_sizes------------------
// Compute the size of first NumberOfLoopInstrToAlign instructions at head
// Compute the size of first NumberOfLoopInstrToAlign instructions at the top
// of a loop. When aligning a loop we need to provide enough instructions
// in cpu's fetch buffer to feed decoders. The loop alignment could be
// avoided if we have enough instructions in fetch buffer at the head of a loop.
@ -284,34 +284,23 @@ void Compile::compute_loop_first_inst_sizes() {
for( uint i=1; i <= last_block; i++ ) {
Block *b = _cfg->_blocks[i];
// Check the first loop's block which requires an alignment.
if( b->head()->is_Loop() &&
b->code_alignment() > (uint)relocInfo::addr_unit() ) {
if( b->loop_alignment() > (uint)relocInfo::addr_unit() ) {
uint sum_size = 0;
uint inst_cnt = NumberOfLoopInstrToAlign;
inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt,
_regalloc);
// Check the next fallthrough block if first loop's block does not have
// enough instructions.
if( inst_cnt > 0 && i < last_block ) {
// First, check if the first loop's block contains whole loop.
// LoopNode::LoopBackControl == 2.
Block *bx = _cfg->_bbs[b->pred(2)->_idx];
// Skip connector blocks (with limit in case of irreducible loops).
int search_limit = 16;
while( bx->is_connector() && search_limit-- > 0) {
bx = _cfg->_bbs[bx->pred(1)->_idx];
}
if( bx != b ) { // loop body is in several blocks.
Block *nb = NULL;
while( inst_cnt > 0 && i < last_block && nb != bx &&
!_cfg->_blocks[i+1]->head()->is_Loop() ) {
i++;
nb = _cfg->_blocks[i];
inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt,
_regalloc);
} // while( inst_cnt > 0 && i < last_block )
} // if( bx != b )
} // if( inst_cnt > 0 && i < last_block )
inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt, _regalloc);
// Check subsequent fallthrough blocks if the loop's first
// block(s) does not have enough instructions.
Block *nb = b;
while( inst_cnt > 0 &&
i < last_block &&
!_cfg->_blocks[i+1]->has_loop_alignment() &&
!nb->has_successor(b) ) {
i++;
nb = _cfg->_blocks[i];
inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt, _regalloc);
} // while( inst_cnt > 0 && i < last_block )
b->set_first_inst_size(sum_size);
} // f( b->head()->is_Loop() )
} // for( i <= last_block )
@ -332,6 +321,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
uint *jmp_end = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks);
uint *blk_starts = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks+1);
DEBUG_ONLY( uint *jmp_target = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); )
DEBUG_ONLY( uint *jmp_rule = NEW_RESOURCE_ARRAY(uint,_cfg->_num_blocks); )
blk_starts[0] = 0;
// Initialize the sizes to 0
@ -443,9 +433,9 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
uintptr_t target = blk_starts[bnum];
if( mach->is_pc_relative() ) {
int offset = target-(blk_starts[i] + jmp_end[i]);
if (_matcher->is_short_branch_offset(offset)) {
if (_matcher->is_short_branch_offset(mach->rule(), offset)) {
// We've got a winner. Replace this branch.
MachNode *replacement = mach->short_branch_version(this);
MachNode* replacement = mach->short_branch_version(this);
b->_nodes.map(j, replacement);
mach->subsume_by(replacement);
@ -453,6 +443,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
// next pass.
jmp_end[i] -= (mach->size(_regalloc) - replacement->size(_regalloc));
DEBUG_ONLY( jmp_target[i] = bnum; );
DEBUG_ONLY( jmp_rule[i] = mach->rule(); );
}
} else {
#ifndef PRODUCT
@ -510,7 +501,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
// Get the size of the block
uint blk_size = adr - blk_starts[i];
// When the next block starts a loop, we may insert pad NOP
// When the next block is the top of a loop, we may insert pad NOP
// instructions.
Block *nb = _cfg->_blocks[i+1];
int current_offset = blk_starts[i] + blk_size;
@ -524,10 +515,10 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
for( i=0; i<_cfg->_num_blocks; i++ ) { // For all blocks
if( jmp_target[i] != 0 ) {
int offset = blk_starts[jmp_target[i]]-(blk_starts[i] + jmp_end[i]);
if (!_matcher->is_short_branch_offset(offset)) {
if (!_matcher->is_short_branch_offset(jmp_rule[i], offset)) {
tty->print_cr("target (%d) - jmp_end(%d) = offset (%d), jmp_block B%d, target_block B%d", blk_starts[jmp_target[i]], blk_starts[i] + jmp_end[i], offset, i, jmp_target[i]);
}
assert(_matcher->is_short_branch_offset(offset), "Displacement too large for short jmp");
assert(_matcher->is_short_branch_offset(jmp_rule[i], offset), "Displacement too large for short jmp");
}
}
#endif
@ -1069,7 +1060,7 @@ void Compile::Fill_buffer() {
// If this machine supports different size branch offsets, then pre-compute
// the length of the blocks
if( _matcher->is_short_branch_offset(0) ) {
if( _matcher->is_short_branch_offset(-1, 0) ) {
Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req);
labels_not_set = false;
}
@ -1380,8 +1371,8 @@ void Compile::Fill_buffer() {
} // End for all instructions in block
// If the next block _starts_ a loop, pad this block out to align
// the loop start a little. Helps prevent pipe stalls at loop starts
// If the next block is the top of a loop, pad this block out to align
// the loop top a little. Helps prevent pipe stalls at loop back branches.
int nop_size = (new (this) MachNopNode())->size(_regalloc);
if( i<_cfg->_num_blocks-1 ) {
Block *nb = _cfg->_blocks[i+1];

View File

@ -46,7 +46,7 @@ elapsedTimer Phase::_t_output;
#ifndef PRODUCT
elapsedTimer Phase::_t_graphReshaping;
elapsedTimer Phase::_t_scheduler;
elapsedTimer Phase::_t_removeEmptyBlocks;
elapsedTimer Phase::_t_blockOrdering;
elapsedTimer Phase::_t_macroExpand;
elapsedTimer Phase::_t_peephole;
elapsedTimer Phase::_t_codeGeneration;
@ -128,7 +128,7 @@ void Phase::print_timers() {
tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc);
}
tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
tty->print_cr (" removeEmpty : %3.3f sec", Phase::_t_removeEmptyBlocks.seconds());
tty->print_cr (" blockOrdering: %3.3f sec", Phase::_t_blockOrdering.seconds());
tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds());
@ -137,7 +137,7 @@ void Phase::print_timers() {
(DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) +
Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() +
Phase::_t_registerAllocation.seconds() + Phase::_t_removeEmptyBlocks.seconds() +
Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() +
Phase::_t_macroExpand.seconds() + Phase::_t_peephole.seconds() +
Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds();
double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -83,12 +83,12 @@ void RegisterMap::print_on(outputStream* st) const {
intptr_t* src = (intptr_t*) location(r);
if (src != NULL) {
r->print();
tty->print(" [" INTPTR_FORMAT "] = ", src);
r->print_on(st);
st->print(" [" INTPTR_FORMAT "] = ", src);
if (((uintptr_t)src & (sizeof(*src)-1)) != 0) {
tty->print_cr("<misaligned>");
st->print_cr("<misaligned>");
} 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: ");
if (_size) {
st->print("requested ");
sprintf(buf,"%d",_size);
sprintf(buf,SIZE_FORMAT,_size);
st->print(buf);
st->print(" bytes");
if (_message != NULL) {

View File

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

View File

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

View File

@ -13,3 +13,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
134fd1a656ea85acd1f97f6700f75029b9b472a0 jdk7-b36
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
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 -->
<!-- At this time, ./build.properties has not been loaded yet. -->
<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}" />
<!-- unchecked warnings will be fixed in JMX 2.0 as part of the work
being done on JSR 255 new features -->
<property name="javac.options"
value="-Xlint -Xlint:-unchecked -Xlint:-deprecation"/>
<property name="javac.options"
value="-Xlint -Xlint:-deprecation"/>
</target>
@ -58,13 +58,13 @@
<!-- Dir to keep generated stub source -->
<mkdir dir="${gensrc.dir}" />
</target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Call rmic-jmx subtargets -->
<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"
description="Generate RMI IIOP stub class files for remote objects. Do not keep generated java files." >
<rmic base="${classes.dir}"
includeAntRuntime="no"
includeJavaRuntime="no"
@ -115,11 +115,11 @@
<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"
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"
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"
description="Jar JMX class files (including RMI stubs)" >
<mkdir dir="${dist.dir}/lib"/>
<jar jarfile="${dist.dir}/lib/${jar.jmx.name}"
<jar jarfile="${dist.dir}/lib/${jar.jmx.name}"
update="true"
index="false"
duplicate="fail">
@ -144,7 +144,7 @@
<attribute name="Specification-Version" value="${jar.jmx.spec.version}" />
<attribute name="Specification-Vendor" value="${jar.jmx.spec.vendor}" />
<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}" />
</section>
</manifest>

View File

@ -141,7 +141,7 @@ public class LeaseManager {
}
private final Runnable callback;
private ScheduledFuture scheduled; // If null, the lease has expired.
private ScheduledFuture<?> scheduled; // If null, the lease has expired.
private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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