--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -2615,7 +2615,8 @@
}
}
-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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
}
if (EmitSync & 8) {
- if (UseBiasedLocking) {
+ if (try_bias) {
biased_locking_exit(mark_addr, Rscratch, done);
}
@@ -3077,7 +3079,7 @@
// I$ effects.
Label LStacked ;
- if (UseBiasedLocking) {
+ if (try_bias) {
// TODO: eliminate redundant LDs of obj->mark
biased_locking_exit(mark_addr, Rscratch, done);
}
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -2220,9 +2220,13 @@
// 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,
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -906,7 +906,7 @@
// 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 {
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Fri Nov 14 19:23:49 2008 -0800
@@ -395,6 +395,7 @@
);
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 @@
//
// 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 @@
$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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"\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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
%}
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -956,7 +956,7 @@
// 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 @@
#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
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -621,6 +621,10 @@
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++) {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -1780,7 +1780,8 @@
// 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);
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Fri Nov 14 19:23:49 2008 -0800
@@ -495,8 +495,8 @@
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 @@
// 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 @@
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 @@
// 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 @@
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_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 @@
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 @@
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_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 @@
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 @@
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 @@
// --------------------------------------
// 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 @@
// 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 @@
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 @@
}
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 @@
// 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 @@
//
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
%}
// 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 @@
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 @@
%}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
//
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Fri Nov 14 19:23:49 2008 -0800
@@ -2004,9 +2004,12 @@
//
// 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 @@
// 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 @@
} else {
Label DONE_LABEL, Stacked, CheckSucc ;
- if (UseBiasedLocking) {
+ if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
}
@@ -5134,6 +5137,15 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
%}
// 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 @@
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 @@
%}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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)
-%{
- match(Set res (StoreLConditional mem_ptr (Binary oldval newval)));
- effect(KILL cr);
-
- 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" %}
+// 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 cr (StoreIConditional mem (Binary oldval newval)));
+ effect(KILL oldval);
+
+ 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)
-%{
- match(Set cr (CmpI (StoreLConditional mem_ptr (Binary oldval newval)) zero));
-
- format %{ "cmpxchgq $mem_ptr, $newval\t# (long) "
- "If rax == $mem_ptr then store $newval into $mem_ptr" %}
+// 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 (StoreLConditional mem (Binary oldval newval)));
+ effect(KILL oldval);
+
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
%}
// 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,39 @@
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));
+ ins_pipe(pipe_jcc);
+ 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));
@@ -11435,6 +11630,46 @@
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 @@
// 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 @@
%}
// 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 @@
%}
// 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,12 +11785,40 @@
%}
// 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);
opcode(0x70);
@@ -11568,9 +11828,7 @@
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 @@
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
--- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.ad Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.ad Fri Nov 14 19:23:49 2008 -0800
@@ -103,16 +103,16 @@
// 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 %{
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad Fri Nov 14 19:23:49 2008 -0800
@@ -110,16 +110,16 @@
// 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 %{
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java Fri Nov 14 19:23:49 2008 -0800
@@ -28,6 +28,7 @@
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 @@
}
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 {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java Fri Nov 14 19:23:49 2008 -0800
@@ -33,7 +33,7 @@
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.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 @@
*/
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;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java Fri Nov 14 19:23:49 2008 -0800
@@ -28,6 +28,7 @@
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 @@
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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java Fri Nov 14 19:23:49 2008 -0800
@@ -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 @@
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 @@
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 @@
@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);
+ }
}
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java Fri Nov 14 19:23:49 2008 -0800
@@ -31,7 +31,7 @@
*
* @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;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java Fri Nov 14 19:23:49 2008 -0800
@@ -37,7 +37,7 @@
*
* @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;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Fri Nov 14 19:23:49 2008 -0800
@@ -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 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 @@
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) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Fri Nov 14 19:23:49 2008 -0800
@@ -32,7 +32,7 @@
*
* @author Thomas Wuerthinger
*/
-public class InputMethod extends Properties.Object {
+public class InputMethod extends Properties.Entity {
private String name;
private int bci;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java Fri Nov 14 19:23:49 2008 -0800
@@ -27,7 +27,7 @@
*
* @author Thomas Wuerthinger
*/
-public class InputNode extends Properties.Object {
+public class InputNode extends Properties.Entity {
private int id;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java Fri Nov 14 19:23:49 2008 -0800
@@ -26,24 +26,22 @@
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 @@
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 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 @@
}
}
+ 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 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 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 String get(String key) {
- Property p = map.get(key);
- if (p == null) {
- return null;
- } else {
- return p.getValue();
+ for (int i = 0; i < map.length; i += 2) {
+ if (map[i] != null && map[i].equals(key)) {
+ return map[i + 1];
+ }
}
- }
-
- public String getProperty(String string) {
- return get(string);
+ return null;
}
- public Property setProperty(String name, String value) {
-
+ 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) {
- // remove this property
- return map.remove(name);
- } else {
- Property p = map.get(name);
- if (p == null) {
- p = new Property(name, value);
- map.put(name, p);
- } else {
- p.setValue(value);
+ return;
+ }
+ for (int i = 0; i < map.length; i += 2) {
+ if (map[i] == null) {
+ map[i] = name;
+ map[i + 1] = value;
+ return;
}
- return p;
}
+ 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 Collection<Property> getProperties() {
- return Collections.unmodifiableCollection(map.values());
+ 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 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();
}
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java Fri Nov 14 19:23:49 2008 -0800
@@ -32,18 +32,19 @@
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 @@
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();
+ }
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Fri Nov 14 19:23:49 2008 -0800
@@ -38,6 +38,7 @@
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 @@
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 @@
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 @@
@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 @@
int id = 0;
try {
- id = Integer.parseInt(s);
+ id = lookupID(s);
} catch (NumberFormatException e) {
throw new SAXException(e);
}
@@ -252,7 +265,7 @@
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 @@
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 @@
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 @@
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 @@
}
};
// <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());
}
};
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java Fri Nov 14 19:23:49 2008 -0800
@@ -67,7 +67,7 @@
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());
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java Fri Nov 14 19:23:49 2008 -0800
@@ -25,7 +25,7 @@
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 @@
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 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 @@
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);
}
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java Fri Nov 14 19:23:49 2008 -0800
@@ -89,7 +89,7 @@
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 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 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();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Fri Nov 14 19:23:49 2008 -0800
@@ -29,6 +29,7 @@
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 @@
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 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 @@
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);
}
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/manifest.mf Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/manifest.mf Fri Nov 14 19:23:49 2008 -0800
@@ -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
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java Fri Nov 14 19:23:49 2008 -0800
@@ -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 CustomFilter(String name, String code) {
this.name = name;
this.code = code;
- getProperties().add(new Property("name", name));
+ getProperties().setProperty("name", name);
}
public String getName() {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java Fri Nov 14 19:23:49 2008 -0800
@@ -56,8 +56,8 @@
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);
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Fri Nov 14 19:23:49 2008 -0800
@@ -35,7 +35,7 @@
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 @@
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);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java Fri Nov 14 19:23:49 2008 -0800
@@ -42,7 +42,7 @@
*
* @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;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java Fri Nov 14 19:23:49 2008 -0800
@@ -26,7 +26,7 @@
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 @@
*/
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>>();
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java Fri Nov 14 19:23:49 2008 -0800
@@ -25,7 +25,7 @@
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 @@
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 @@
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);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java Fri Nov 14 19:23:49 2008 -0800
@@ -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 @@
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 @@
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();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/README Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/README Fri Nov 14 19:23:49 2008 -0800
@@ -5,21 +5,16 @@
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:
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java Fri Nov 14 19:23:49 2008 -0800
@@ -36,11 +36,11 @@
*/
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 @@
@Override
public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- p.setValue(arg0);
+ properties.setProperty(p.getName(), arg0);
}
};
prop.setName(p.getName());
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java Fri Nov 14 19:23:49 2008 -0800
@@ -65,13 +65,19 @@
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) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java Fri Nov 14 19:23:49 2008 -0800
@@ -63,7 +63,7 @@
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 @@
*/
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 @@
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 @@
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();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java Fri Nov 14 19:23:49 2008 -0800
@@ -55,6 +55,7 @@
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 @@
}
};
+ @Override
public DiagramViewModel copy() {
DiagramViewModel result = new DiagramViewModel(group, filterChain, sequenceFilterChain);
result.setData(this);
@@ -79,6 +81,7 @@
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 @@
viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
this.showNodeHull = newModel.showNodeHull;
+ if(groupChanged) {
+ groupChangedEvent.fire();
+ }
+
if (diagramChanged) {
diagramChangedEvent.fire();
}
@@ -143,11 +150,38 @@
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 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) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java Fri Nov 14 19:23:49 2008 -0800
@@ -67,7 +67,7 @@
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());
}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties Fri Nov 14 19:23:49 2008 -0800
@@ -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 @@
org.openide.execution,\
org.openide.util.enumerations
enabled.clusters=\
- platform7
+ platform8
nbjdk.active=default
nbplatform.active=default
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Fri Nov 14 19:23:49 2008 -0800
@@ -15,7 +15,6 @@
${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.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
--- a/hotspot/src/share/vm/adlc/adlparse.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -33,7 +33,6 @@
_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 @@
}
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
+//------------------------------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 @@
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 @@
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 @@
//---------------------------next_line-----------------------------------------
void ADLParser::next_line() {
- _curline = _buf.get_line(); _linenum++;
+ _curline = _buf.get_line();
}
//-------------------------is_literal_constant---------------------------------
--- a/hotspot/src/share/vm/adlc/adlparse.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/adlparse.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -70,7 +70,6 @@
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 @@
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 @@
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);
--- a/hotspot/src/share/vm/adlc/filebuff.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/filebuff.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -41,6 +41,7 @@
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 @@
// 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
--- a/hotspot/src/share/vm/adlc/filebuff.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/filebuff.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -51,6 +51,7 @@
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 @@
// 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()).
--- a/hotspot/src/share/vm/adlc/forms.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/forms.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -35,6 +35,8 @@
//------------------------------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) {
--- a/hotspot/src/share/vm/adlc/forms.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/forms.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -329,6 +329,8 @@
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);
--- a/hotspot/src/share/vm/adlc/formssel.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -1574,10 +1574,10 @@
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 @@
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 @@
}
//------------------------------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 @@
"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"
--- a/hotspot/src/share/vm/adlc/formssel.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -397,7 +397,7 @@
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 @@
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();
--- a/hotspot/src/share/vm/adlc/output_c.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/output_c.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -1619,6 +1619,7 @@
}
// 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 @@
// 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 @@
_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 @@
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)) {
--- a/hotspot/src/share/vm/adlc/output_h.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/adlc/output_h.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -355,17 +355,19 @@
// ---------------------------------------------------------------------------
// 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 @@
++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 @@
++i;
}
else if (!strcmp(ideal_type, "Bool")) {
- defineCCodeDump(fp,i);
+ defineCCodeDump(oper, fp,i);
++i;
}
@@ -476,7 +478,7 @@
}
// 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 @@
}
// 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 @@
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 @@
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 @@
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)
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -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 @@
_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;
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -54,13 +54,19 @@
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 @@
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 @@
// 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);
}
}
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -340,8 +340,10 @@
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; }
--- a/hotspot/src/share/vm/opto/block.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/block.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -57,6 +57,14 @@
_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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
_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 @@
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 @@
}
}
// 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 @@
// 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 @@
}
// 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 @@
// 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 @@
}
// 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 @@
// 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 @@
// 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 @@
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 @@
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);
+ }
+ }
+ }
+ }
+ }
+}
--- a/hotspot/src/share/vm/opto/block.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/block.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -75,6 +75,7 @@
void insert( uint i, Block *n );
uint size() const { return _cnt; }
void reset() { _cnt = 0; }
+ void print();
};
@@ -129,7 +130,11 @@
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 @@
// 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 @@
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 @@
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 @@
_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 @@
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 @@
// 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 @@
// 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 @@
};
-//------------------------------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 @@
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);
+};
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -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)
--- a/hotspot/src/share/vm/opto/callnode.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/callnode.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -967,6 +967,7 @@
init_class_id(Class_SafePointScalarObject);
}
+bool SafePointScalarObjectNode::pinned() const { return true; }
uint SafePointScalarObjectNode::ideal_reg() const {
return 0; // No matching to machine instruction
--- a/hotspot/src/share/vm/opto/callnode.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/callnode.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -433,6 +433,10 @@
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
--- a/hotspot/src/share/vm/opto/chaitin.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -440,9 +440,7 @@
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;
--- a/hotspot/src/share/vm/opto/classes.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/classes.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -205,6 +205,7 @@
macro(StoreC)
macro(StoreCM)
macro(StorePConditional)
+macro(StoreIConditional)
macro(StoreLConditional)
macro(StoreD)
macro(StoreF)
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -551,7 +551,7 @@
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 @@
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 @@
// 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 @@
case Op_StorePConditional:
case Op_StoreI:
case Op_StoreL:
+ case Op_StoreIConditional:
case Op_StoreLConditional:
case Op_CompareAndSwapI:
case Op_CompareAndSwapL:
--- a/hotspot/src/share/vm/opto/compile.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -154,6 +154,7 @@
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 @@
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; }
--- a/hotspot/src/share/vm/opto/gcm.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/gcm.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -1319,11 +1319,33 @@
//------------------------------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,25 +1355,27 @@
_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);
+ 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 = 0; i < uct->num_preds(); i++) {
- Block *pb = _bbs[uct->pred(i)->_idx];
- if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) {
- worklist.push(pb);
+ 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);
+ }
}
}
}
@@ -1556,22 +1580,6 @@
}
}
-#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 @@
// 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 @@
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.
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -3485,11 +3485,32 @@
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);
-
- push(result);
+ Node *bol = _gvn.transform( new (C, 2) BoolNode( cas, BoolTest::eq ) );
+
+ 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;
}
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -1519,6 +1519,7 @@
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 ) ||
--- a/hotspot/src/share/vm/opto/macro.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/macro.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -82,16 +82,31 @@
}
}
-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 @@
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 @@
Node* flock = lock->fastlock_node();
// Make the merge point
- Node *region = new (C, 3) RegionNode(3);
+ Node *region;
+ Node *mem_phi;
+ Node *slow_path;
+
+ 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).
+
- 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);
+ // 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 @@
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 @@
// 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 @@
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----------------------
--- a/hotspot/src/share/vm/opto/macro.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/macro.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -93,7 +93,7 @@
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);
--- a/hotspot/src/share/vm/opto/matcher.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/matcher.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -1951,6 +1951,7 @@
// 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:
--- a/hotspot/src/share/vm/opto/matcher.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/matcher.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -324,7 +324,7 @@
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;
--- a/hotspot/src/share/vm/opto/memnode.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/memnode.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -227,6 +227,14 @@
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;
--- a/hotspot/src/share/vm/opto/memnode.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/memnode.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -632,6 +632,17 @@
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 @@
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; }
};
--- a/hotspot/src/share/vm/opto/output.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -263,7 +263,7 @@
# 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
} // 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];
--- a/hotspot/src/share/vm/opto/phase.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/phase.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -46,7 +46,7 @@
#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 @@
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 @@
(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;
--- a/hotspot/src/share/vm/opto/phase.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/phase.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -40,16 +40,12 @@
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 @@
#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;
--- a/hotspot/src/share/vm/opto/reg_split.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/reg_split.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -53,6 +53,7 @@
// 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;
}
--- a/hotspot/src/share/vm/opto/type.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/type.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -3541,7 +3541,7 @@
#ifndef PRODUCT
void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const {
- tty->print("narrowoop: ");
+ st->print("narrowoop: ");
_ooptype->dump2(d, depth, st);
}
#endif
--- a/hotspot/src/share/vm/opto/type.hpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/opto/type.hpp Fri Nov 14 19:23:49 2008 -0800
@@ -1183,6 +1183,9 @@
#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 @@
#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
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -1365,6 +1365,9 @@
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 @@
FLAG_SET_DEFAULT(UseBiasedLocking, false);
#endif /* CC_INTERP */
+#ifdef COMPILER2
+ if (!UseBiasedLocking || EmitSync != 0) {
+ UseOptoBiasInlining = false;
+ }
+#endif
+
if (PrintCommandLineFlags) {
CommandLineFlags::printSetFlags();
}
--- a/hotspot/src/share/vm/runtime/frame.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/runtime/frame.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -83,12 +83,12 @@
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);
}
}
}
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu Nov 06 12:10:20 2008 -0800
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Nov 14 19:23:49 2008 -0800
@@ -263,7 +263,7 @@
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) {