< prev index next >
src/hotspot/cpu/sparc/macroAssembler_sparc.cpp
Print this page
rev 51633 : imported patch 8210381
*** 2646,2759 ****
if (counters != NULL) {
inc_counter((address) counters->total_entry_count_addr(), Rmark, Rscratch);
}
- if (EmitSync & 1) {
- mov(3, Rscratch);
- st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes());
- cmp(SP, G0);
- return ;
- }
-
- if (EmitSync & 2) {
-
- // Fetch object's markword
- ld_ptr(mark_addr, Rmark);
-
- if (try_bias) {
- biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters);
- }
-
- // Save Rbox in Rscratch to be used for the cas operation
- mov(Rbox, Rscratch);
-
- // set Rmark to markOop | markOopDesc::unlocked_value
- or3(Rmark, markOopDesc::unlocked_value, Rmark);
-
- // Initialize the box. (Must happen before we update the object mark!)
- st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes());
-
- // compare object markOop with Rmark and if equal exchange Rscratch with object markOop
- assert(mark_addr.disp() == 0, "cas must take a zero displacement");
- cas_ptr(mark_addr.base(), Rmark, Rscratch);
-
- // if compare/exchange succeeded we found an unlocked object and we now have locked it
- // hence we are done
- cmp(Rmark, Rscratch);
- sub(Rscratch, STACK_BIAS, Rscratch);
- brx(Assembler::equal, false, Assembler::pt, done);
- delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot
-
- // we did not find an unlocked object so see if this is a recursive case
- // sub(Rscratch, SP, Rscratch);
- assert(os::vm_page_size() > 0xfff, "page size too small - change the constant");
- andcc(Rscratch, 0xfffff003, Rscratch);
- st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes());
- bind (done);
- return ;
- }
-
Label Egress ;
- if (EmitSync & 256) {
- Label IsInflated ;
-
- ld_ptr(mark_addr, Rmark); // fetch obj->mark
- // Triage: biased, stack-locked, neutral, inflated
- 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.
- }
-
- // Store mark into displaced mark field in the on-stack basic-lock "box"
- // Critically, this must happen before the CAS
- // Maximize the ST-CAS distance to minimize the ST-before-CAS penalty.
- st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes());
- andcc(Rmark, 2, G0);
- brx(Assembler::notZero, false, Assembler::pn, IsInflated);
- delayed()->
-
- // Try stack-lock acquisition.
- // Beware: the 1st instruction is in a delay slot
- mov(Rbox, Rscratch);
- or3(Rmark, markOopDesc::unlocked_value, Rmark);
- assert(mark_addr.disp() == 0, "cas must take a zero displacement");
- cas_ptr(mark_addr.base(), Rmark, Rscratch);
- cmp(Rmark, Rscratch);
- brx(Assembler::equal, false, Assembler::pt, done);
- delayed()->sub(Rscratch, SP, Rscratch);
-
- // Stack-lock attempt failed - check for recursive stack-lock.
- // See the comments below about how we might remove this case.
- sub(Rscratch, STACK_BIAS, Rscratch);
- assert(os::vm_page_size() > 0xfff, "page size too small - change the constant");
- andcc(Rscratch, 0xfffff003, Rscratch);
- br(Assembler::always, false, Assembler::pt, done);
- delayed()-> st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes());
-
- bind(IsInflated);
- if (EmitSync & 64) {
- // If m->owner != null goto IsLocked
- // Pessimistic form: Test-and-CAS vs CAS
- // The optimistic form avoids RTS->RTO cache line upgrades.
- ld_ptr(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rscratch);
- andcc(Rscratch, Rscratch, G0);
- brx(Assembler::notZero, false, Assembler::pn, done);
- delayed()->nop();
- // m->owner == null : it's unlocked.
- }
-
- // Try to CAS m->owner from null to Self
- // Invariant: if we acquire the lock then _recursions should be 0.
- add(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rmark);
- mov(G2_thread, Rscratch);
- cas_ptr(Rmark, G0, Rscratch);
- cmp(Rscratch, G0);
- // Intentional fall-through into done
- } else {
// Aggressively avoid the Store-before-CAS penalty
// Defer the store into box->dhw until after the CAS
Label IsInflated, Recursive ;
// Anticipate CAS -- Avoid RTS->RTO upgrade
--- 2646,2657 ----
*** 2834,2844 ****
// ST box->displaced_header = NonZero.
// Any non-zero value suffices:
// markOopDesc::unused_mark(), G2_thread, RBox, RScratch, rsp, etc.
st_ptr(Rbox, Rbox, BasicLock::displaced_header_offset_in_bytes());
// Intentional fall-through into done
- }
bind (done);
}
void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
--- 2732,2741 ----
*** 2846,2879 ****
bool try_bias) {
Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
Label done ;
- if (EmitSync & 4) {
- cmp(SP, G0);
- return ;
- }
-
- if (EmitSync & 8) {
- if (try_bias) {
- biased_locking_exit(mark_addr, Rscratch, done);
- }
-
- // Test first if it is a fast recursive unlock
- ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rmark);
- br_null_short(Rmark, Assembler::pt, done);
-
- // Check if it is still a light weight lock, this is is true if we see
- // the stack address of the basicLock in the markOop of the object
- assert(mark_addr.disp() == 0, "cas must take a zero displacement");
- cas_ptr(mark_addr.base(), Rbox, Rmark);
- ba(done);
- delayed()->cmp(Rbox, Rmark);
- bind(done);
- return ;
- }
-
// Beware ... If the aggregate size of the code emitted by CLO and CUO is
// is too large performance rolls abruptly off a cliff.
// This could be related to inlining policies, code cache management, or
// I$ effects.
Label LStacked ;
--- 2743,2752 ----
*** 2900,2987 ****
// and that particular flavor of barrier is a noop, so we can safely elide it.
// Note that we use 1-0 locking by default for the inflated case. We
// close the resultant (and rare) race by having contended threads in
// monitorenter periodically poll _owner.
- if (EmitSync & 1024) {
- // Emit code to check that _owner == Self
- // We could fold the _owner test into subsequent code more efficiently
- // than using a stand-alone check, but since _owner checking is off by
- // default we don't bother. We also might consider predicating the
- // _owner==Self check on Xcheck:jni or running on a debug build.
- ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), Rscratch);
- orcc(Rscratch, G0, G0);
- brx(Assembler::notZero, false, Assembler::pn, done);
- delayed()->nop();
- }
-
- if (EmitSync & 512) {
- // classic lock release code absent 1-0 locking
- // m->Owner = null;
- // membar #storeload
- // if (m->cxq|m->EntryList) == null goto Success
- // if (m->succ != null) goto Success
- // if CAS (&m->Owner,0,Self) != 0 goto Success
- // goto SlowPath
- ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), Rbox);
- orcc(Rbox, G0, G0);
- brx(Assembler::notZero, false, Assembler::pn, done);
- delayed()->nop();
- st_ptr(G0, Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
- if (os::is_MP()) { membar(StoreLoad); }
- ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)), Rscratch);
- ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)), Rbox);
- orcc(Rbox, Rscratch, G0);
- brx(Assembler::zero, false, Assembler::pt, done);
- delayed()->
- ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), Rscratch);
- andcc(Rscratch, Rscratch, G0);
- brx(Assembler::notZero, false, Assembler::pt, done);
- delayed()->andcc(G0, G0, G0);
- add(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), Rmark);
- mov(G2_thread, Rscratch);
- cas_ptr(Rmark, G0, Rscratch);
- cmp(Rscratch, G0);
- // invert icc.zf and goto done
- brx(Assembler::notZero, false, Assembler::pt, done);
- delayed()->cmp(G0, G0);
- br(Assembler::always, false, Assembler::pt, done);
- delayed()->cmp(G0, 1);
- } else {
// 1-0 form : avoids CAS and MEMBAR in the common case
// Do not bother to ratify that m->Owner == Self.
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), Rbox);
orcc(Rbox, G0, G0);
brx(Assembler::notZero, false, Assembler::pn, done);
delayed()->
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)), Rscratch);
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)), Rbox);
orcc(Rbox, Rscratch, G0);
- if (EmitSync & 16384) {
- // As an optional optimization, if (EntryList|cxq) != null and _succ is null then
- // we should transfer control directly to the slow-path.
- // This test makes the reacquire operation below very infrequent.
- // The logic is equivalent to :
- // if (cxq|EntryList) == null : Owner=null; goto Success
- // if succ == null : goto SlowPath
- // Owner=null; membar #storeload
- // if succ != null : goto Success
- // if CAS(&Owner,null,Self) != null goto Success
- // goto SlowPath
- brx(Assembler::zero, true, Assembler::pt, done);
- delayed()->
- st_ptr(G0, Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
- ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), Rscratch);
- andcc(Rscratch, Rscratch, G0) ;
- brx(Assembler::zero, false, Assembler::pt, done);
- delayed()->orcc(G0, 1, G0);
- st_ptr(G0, Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
- } else {
brx(Assembler::zero, false, Assembler::pt, done);
delayed()->
st_ptr(G0, Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
! }
if (os::is_MP()) { membar(StoreLoad); }
// Check that _succ is (or remains) non-zero
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), Rscratch);
andcc(Rscratch, Rscratch, G0);
brx(Assembler::notZero, false, Assembler::pt, done);
--- 2773,2795 ----
// and that particular flavor of barrier is a noop, so we can safely elide it.
// Note that we use 1-0 locking by default for the inflated case. We
// close the resultant (and rare) race by having contended threads in
// monitorenter periodically poll _owner.
// 1-0 form : avoids CAS and MEMBAR in the common case
// Do not bother to ratify that m->Owner == Self.
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), Rbox);
orcc(Rbox, G0, G0);
brx(Assembler::notZero, false, Assembler::pn, done);
delayed()->
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)), Rscratch);
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)), Rbox);
orcc(Rbox, Rscratch, G0);
brx(Assembler::zero, false, Assembler::pt, done);
delayed()->
st_ptr(G0, Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
!
if (os::is_MP()) { membar(StoreLoad); }
// Check that _succ is (or remains) non-zero
ld_ptr(Address(Rmark, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), Rscratch);
andcc(Rscratch, Rscratch, G0);
brx(Assembler::notZero, false, Assembler::pt, done);
*** 2998,3008 ****
// In v8+ mode the idiom would be valid IFF Rscratch was a G or O register
brx(Assembler::notZero, false, Assembler::pt, done);
delayed()->cmp(G0, G0);
br(Assembler::always, false, Assembler::pt, done);
delayed()->cmp(G0, 1);
- }
bind (LStacked);
// Consider: we could replace the expensive CAS in the exit
// path with a simple ST of the displaced mark value fetched from
// the on-stack basiclock box. That admits a race where a thread T2
--- 2806,2815 ----
< prev index next >