Merge
This commit is contained in:
commit
0f58116e47
@ -13,3 +13,4 @@ bb1ef4ee3d2c8cbf43a37d372325a7952be590b9 jdk7-b33
|
||||
4b4f5fea8d7d0743f0c30d91fcd9bf9d96e5d2ad jdk7-b36
|
||||
744554f5a3290e11c71cd2ddb1aff49e431f9ed0 jdk7-b37
|
||||
cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38
|
||||
ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39
|
||||
|
@ -13,3 +13,4 @@ ef6af34d75a7b44e77083f1d4ee47631fa09d3b4 jdk7-b31
|
||||
0723891eb8d1c27e67c54163af0b4cea05a4e036 jdk7-b36
|
||||
59d5848bdedebe91cc2753acce78911bcb4a66db jdk7-b37
|
||||
08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38
|
||||
55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39
|
||||
|
@ -13,3 +13,4 @@ b727c32788a906c04839516ae7443a085185a300 jdk7-b32
|
||||
e91159f921a58af3698e6479ea1fc5818da66d09 jdk7-b36
|
||||
9ee9cf798b59e7d51f8c0a686959f313867a55d6 jdk7-b37
|
||||
d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38
|
||||
49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
%}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 %{
|
||||
|
@ -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 %{
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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>>();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -33,7 +33,6 @@ ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc)
|
||||
_globalNames(archDesc.globalNames()) {
|
||||
_AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
|
||||
_AD._warnings = 0; // No warnings either
|
||||
_linenum = 0; // Will increment to first line
|
||||
_curline = _ptr = NULL; // No pointers into buffer yet
|
||||
|
||||
_preproc_depth = 0;
|
||||
@ -76,7 +75,7 @@ ADLParser::~ADLParser() {
|
||||
}
|
||||
if (!_AD._quiet_mode)
|
||||
fprintf(stderr,"-----------------------------------------------------------------------------\n");
|
||||
_AD._TotalLines += _linenum-1; // -1 for overshoot in "nextline" routine
|
||||
_AD._TotalLines += linenum()-1; // -1 for overshoot in "nextline" routine
|
||||
|
||||
// Write out information we have stored
|
||||
// // UNIXism == fsync(stderr);
|
||||
@ -148,7 +147,7 @@ void ADLParser::instr_parse(void) {
|
||||
if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
|
||||
return;
|
||||
instr = new InstructForm(ident); // Create new instruction form
|
||||
instr->_linenum = _linenum;
|
||||
instr->_linenum = linenum();
|
||||
_globalNames.Insert(ident, instr); // Add name to the name table
|
||||
// Debugging Stuff
|
||||
if (_AD._adl_debug > 1)
|
||||
@ -404,7 +403,7 @@ void ADLParser::oper_parse(void) {
|
||||
if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
|
||||
return;
|
||||
oper = new OperandForm(ident); // Create new operand form
|
||||
oper->_linenum = _linenum;
|
||||
oper->_linenum = linenum();
|
||||
_globalNames.Insert(ident, oper); // Add name to the name table
|
||||
|
||||
// Debugging Stuff
|
||||
@ -774,7 +773,7 @@ void ADLParser::reg_parse(void) {
|
||||
|
||||
// Create the RegisterForm for the architecture description.
|
||||
RegisterForm *regBlock = new RegisterForm(); // Build new Source object
|
||||
regBlock->_linenum = _linenum;
|
||||
regBlock->_linenum = linenum();
|
||||
_AD.addForm(regBlock);
|
||||
|
||||
skipws(); // Skip leading whitespace
|
||||
@ -847,7 +846,7 @@ void ADLParser::enc_class_parse(void) {
|
||||
}
|
||||
|
||||
EncClass *encoding = _AD._encode->add_EncClass(ec_name);
|
||||
encoding->_linenum = _linenum;
|
||||
encoding->_linenum = linenum();
|
||||
|
||||
skipws(); // Skip leading whitespace
|
||||
// Check for optional parameter list
|
||||
@ -905,7 +904,7 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
|
||||
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
|
||||
if (_AD._adlocation_debug) {
|
||||
const char* file = _AD._ADL_file._name;
|
||||
int line = _linenum;
|
||||
int line = linenum();
|
||||
char* location = (char *)malloc(strlen(file) + 100);
|
||||
sprintf(location, "#line %d \"%s\"\n", line, file);
|
||||
encoding->add_code(location);
|
||||
@ -2776,7 +2775,7 @@ InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
|
||||
|
||||
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
|
||||
EncClass *encoding = _AD._encode->add_EncClass(ec_name);
|
||||
encoding->_linenum = _linenum;
|
||||
encoding->_linenum = linenum();
|
||||
|
||||
// synthesize the arguments list for the enc_class from the
|
||||
// arguments to the instruct definition.
|
||||
@ -2852,7 +2851,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
|
||||
skipws();
|
||||
|
||||
InsEncode *encrule = new InsEncode(); // Encode class for instruction
|
||||
encrule->_linenum = _linenum;
|
||||
encrule->_linenum = linenum();
|
||||
char *ec_name = NULL; // String representation of encode rule
|
||||
// identifier is optional.
|
||||
while (_curchar != ')') {
|
||||
@ -3203,6 +3202,12 @@ Interface *ADLParser::cond_interface_parse(void) {
|
||||
char *greater_equal;
|
||||
char *less_equal;
|
||||
char *greater;
|
||||
const char *equal_format = "eq";
|
||||
const char *not_equal_format = "ne";
|
||||
const char *less_format = "lt";
|
||||
const char *greater_equal_format = "ge";
|
||||
const char *less_equal_format = "le";
|
||||
const char *greater_format = "gt";
|
||||
|
||||
if (_curchar != '%') {
|
||||
parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
|
||||
@ -3222,22 +3227,22 @@ Interface *ADLParser::cond_interface_parse(void) {
|
||||
return NULL;
|
||||
}
|
||||
if ( strcmp(field,"equal") == 0 ) {
|
||||
equal = interface_field_parse();
|
||||
equal = interface_field_parse(&equal_format);
|
||||
}
|
||||
else if ( strcmp(field,"not_equal") == 0 ) {
|
||||
not_equal = interface_field_parse();
|
||||
not_equal = interface_field_parse(¬_equal_format);
|
||||
}
|
||||
else if ( strcmp(field,"less") == 0 ) {
|
||||
less = interface_field_parse();
|
||||
less = interface_field_parse(&less_format);
|
||||
}
|
||||
else if ( strcmp(field,"greater_equal") == 0 ) {
|
||||
greater_equal = interface_field_parse();
|
||||
greater_equal = interface_field_parse(&greater_equal_format);
|
||||
}
|
||||
else if ( strcmp(field,"less_equal") == 0 ) {
|
||||
less_equal = interface_field_parse();
|
||||
less_equal = interface_field_parse(&less_equal_format);
|
||||
}
|
||||
else if ( strcmp(field,"greater") == 0 ) {
|
||||
greater = interface_field_parse();
|
||||
greater = interface_field_parse(&greater_format);
|
||||
}
|
||||
else {
|
||||
parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n");
|
||||
@ -3252,14 +3257,18 @@ Interface *ADLParser::cond_interface_parse(void) {
|
||||
next_char(); // Skip '}'
|
||||
|
||||
// Construct desired object and return
|
||||
Interface *inter = new CondInterface(equal, not_equal, less, greater_equal,
|
||||
less_equal, greater);
|
||||
Interface *inter = new CondInterface(equal, equal_format,
|
||||
not_equal, not_equal_format,
|
||||
less, less_format,
|
||||
greater_equal, greater_equal_format,
|
||||
less_equal, less_equal_format,
|
||||
greater, greater_format);
|
||||
return inter;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------interface_field_parse--------------------------
|
||||
char *ADLParser::interface_field_parse(void) {
|
||||
char *ADLParser::interface_field_parse(const char ** format) {
|
||||
char *iface_field = NULL;
|
||||
|
||||
// Get interface field
|
||||
@ -3280,6 +3289,32 @@ char *ADLParser::interface_field_parse(void) {
|
||||
return NULL;
|
||||
}
|
||||
skipws();
|
||||
if (format != NULL && _curchar == ',') {
|
||||
next_char();
|
||||
skipws();
|
||||
if (_curchar != '"') {
|
||||
parse_err(SYNERR, "Missing '\"' in field format .\n");
|
||||
return NULL;
|
||||
}
|
||||
next_char();
|
||||
char *start = _ptr; // Record start of the next string
|
||||
while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
|
||||
if (_curchar == '\\') next_char(); // superquote
|
||||
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
|
||||
next_char();
|
||||
}
|
||||
if (_curchar != '"') {
|
||||
parse_err(SYNERR, "Missing '\"' at end of field format .\n");
|
||||
return NULL;
|
||||
}
|
||||
// If a string was found, terminate it and record in FormatRule
|
||||
if ( start != _ptr ) {
|
||||
*_ptr = '\0'; // Terminate the string
|
||||
*format = start;
|
||||
}
|
||||
next_char();
|
||||
skipws();
|
||||
}
|
||||
if (_curchar != ')') {
|
||||
parse_err(SYNERR, "Missing ')' after interface field.\n");
|
||||
return NULL;
|
||||
@ -3342,6 +3377,12 @@ FormatRule* ADLParser::format_parse(void) {
|
||||
next_char(); // Move past the '{'
|
||||
|
||||
skipws();
|
||||
if (_curchar == '$') {
|
||||
char* ident = get_rep_var_ident();
|
||||
if (strcmp(ident, "$$template") == 0) return template_parse();
|
||||
parse_err(SYNERR, "Unknown \"%s\" directive in format", ident);
|
||||
return NULL;
|
||||
}
|
||||
// Check for the opening '"' inside the format description
|
||||
if ( _curchar == '"' ) {
|
||||
next_char(); // Move past the initial '"'
|
||||
@ -3433,6 +3474,131 @@ FormatRule* ADLParser::format_parse(void) {
|
||||
}
|
||||
|
||||
|
||||
//------------------------------template_parse-----------------------------------
|
||||
FormatRule* ADLParser::template_parse(void) {
|
||||
char *desc = NULL;
|
||||
FormatRule *format = (new FormatRule(desc));
|
||||
|
||||
skipws();
|
||||
while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
|
||||
|
||||
// (1)
|
||||
// Check if there is a string to pass through to output
|
||||
char *start = _ptr; // Record start of the next string
|
||||
while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
|
||||
// If at the start of a comment, skip past it
|
||||
if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
|
||||
skipws_no_preproc();
|
||||
} else {
|
||||
// ELSE advance to the next character, or start of the next line
|
||||
next_char_or_line();
|
||||
}
|
||||
}
|
||||
// If a string was found, terminate it and record in EncClass
|
||||
if ( start != _ptr ) {
|
||||
*_ptr = '\0'; // Terminate the string
|
||||
// Add flag to _strings list indicating we should check _rep_vars
|
||||
format->_strings.addName(NameList::_signal2);
|
||||
format->_strings.addName(start);
|
||||
}
|
||||
|
||||
// (2)
|
||||
// If we are at a replacement variable,
|
||||
// copy it and record in EncClass
|
||||
if ( _curchar == '$' ) {
|
||||
// Found replacement Variable
|
||||
char *rep_var = get_rep_var_ident_dup();
|
||||
if (strcmp(rep_var, "$emit") == 0) {
|
||||
// switch to normal format parsing
|
||||
next_char();
|
||||
next_char();
|
||||
skipws();
|
||||
// Check for the opening '"' inside the format description
|
||||
if ( _curchar == '"' ) {
|
||||
next_char(); // Move past the initial '"'
|
||||
if( _curchar == '"' ) { // Handle empty format string case
|
||||
*_ptr = '\0'; // Terminate empty string
|
||||
format->_strings.addName(_ptr);
|
||||
}
|
||||
|
||||
// Collect the parts of the format description
|
||||
// (1) strings that are passed through to tty->print
|
||||
// (2) replacement/substitution variable, preceeded by a '$'
|
||||
// (3) multi-token ANSIY C style strings
|
||||
while ( true ) {
|
||||
if ( _curchar == '%' || _curchar == '\n' ) {
|
||||
parse_err(SYNERR, "missing '\"' at end of format block");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// (1)
|
||||
// Check if there is a string to pass through to output
|
||||
char *start = _ptr; // Record start of the next string
|
||||
while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
|
||||
if (_curchar == '\\') next_char(); // superquote
|
||||
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
|
||||
next_char();
|
||||
}
|
||||
// If a string was found, terminate it and record in FormatRule
|
||||
if ( start != _ptr ) {
|
||||
*_ptr = '\0'; // Terminate the string
|
||||
format->_strings.addName(start);
|
||||
}
|
||||
|
||||
// (2)
|
||||
// If we are at a replacement variable,
|
||||
// copy it and record in FormatRule
|
||||
if ( _curchar == '$' ) {
|
||||
next_char(); // Move past the '$'
|
||||
char* rep_var = get_ident(); // Nil terminate the variable name
|
||||
rep_var = strdup(rep_var);// Copy the string
|
||||
*_ptr = _curchar; // and replace Nil with original character
|
||||
format->_rep_vars.addName(rep_var);
|
||||
// Add flag to _strings list indicating we should check _rep_vars
|
||||
format->_strings.addName(NameList::_signal);
|
||||
}
|
||||
|
||||
// (3)
|
||||
// Allow very long strings to be broken up,
|
||||
// using the ANSI C syntax "foo\n" <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---------------------------------
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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()).
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -205,6 +205,7 @@ macro(StoreB)
|
||||
macro(StoreC)
|
||||
macro(StoreCM)
|
||||
macro(StorePConditional)
|
||||
macro(StoreIConditional)
|
||||
macro(StoreLConditional)
|
||||
macro(StoreD)
|
||||
macro(StoreF)
|
||||
|
@ -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:
|
||||
|
@ -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; }
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 ) ||
|
||||
|
@ -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----------------------
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -13,3 +13,4 @@ eac46d1eb7f0935ba04f1c7929ec15423fd0309e jdk7-b35
|
||||
c84ca638db42a8b6b227b4e3b63bca192c5ca634 jdk7-b36
|
||||
af49591bc486d82aa04b832257de0d18adc9af52 jdk7-b37
|
||||
e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38
|
||||
831b80be6cea8e7d7da197ccdac5fd4c701a5033 jdk7-b39
|
||||
|
@ -13,3 +13,4 @@ b0f01c2508b690dd225298edfec70b5e8b8dc367 jdk7-b35
|
||||
f60187f44a0d62906a5e2f6bd0989b5b24c1ca1e jdk7-b36
|
||||
a2a6f9edf761934faf59ea60d7fe7178371302cd jdk7-b37
|
||||
9ce439969184c753a9ba3caf8ed277b05230f2e5 jdk7-b38
|
||||
077bc9b1b035a409a76bd5366f73ed9dd9846934 jdk7-b39
|
||||
|
@ -13,3 +13,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
|
||||
134fd1a656ea85acd1f97f6700f75029b9b472a0 jdk7-b36
|
||||
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
|
||||
cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38
|
||||
4e51997582effa006dde5c6d8b8820b2045b9c7f jdk7-b39
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
|
@ -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 " +
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user