< prev index next > src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
Print this page
Register tmp2Reg, Register tmp3Reg) {
Register oop = objectReg;
Register box = boxReg;
Register disp_hdr = tmpReg;
Register tmp = tmp2Reg;
- Label cont;
Label object_has_monitor;
Label count, no_count;
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
- assert_different_registers(oop, box, tmp, disp_hdr);
+ assert_different_registers(oop, box, tmp, disp_hdr, rscratch1);
// Load markWord from object into displaced_header.
ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, oop);
ldrw(tmp, Address(tmp, Klass::access_flags_offset()));
tstw(tmp, JVM_ACC_IS_VALUE_BASED_CLASS);
- br(Assembler::NE, cont);
+ br(Assembler::NE, no_count);
}
// Check for existing monitor
tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
if (LockingMode == LM_MONITOR) {
tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
- b(cont);
+ b(no_count);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Set tmp to be (markWord of object | UNLOCK_VALUE).
orr(tmp, disp_hdr, markWord::unlocked_value);
// Compare object markWord with an unlocked value (tmp) and if
// equal exchange the stack address of our box with object markWord.
// On failure disp_hdr contains the possibly locked markWord.
cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, disp_hdr);
- br(Assembler::EQ, cont);
+ br(Assembler::EQ, count);
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// If the compare-and-exchange succeeded, then we found an unlocked
// object, will have now locked it will continue at label cont
mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
// If condition is true we are cont and hence we can store 0 as the
// displaced header in the box, which indicates that it is a recursive lock.
ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result
str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- b(cont);
+ b(no_count);
}
// Handle existing monitor.
bind(object_has_monitor);
// The object's monitor m is unlocked iff m->owner == nullptr,
- // otherwise m->owner may contain a thread or a stack address.
+ // otherwise m->owner may contain a thread id, a stack address for LM_LEGACY,
+ // or the ANONYMOUS_OWNER constant for LM_LIGHTWEIGHT.
//
// Try to CAS m->owner from null to current thread.
+ ldr(rscratch2, Address(rthread, JavaThread::lock_id_offset()));
add(tmp, disp_hdr, (in_bytes(ObjectMonitor::owner_offset())-markWord::monitor_value));
- cmpxchg(tmp, zr, rthread, Assembler::xword, /*acquire*/ true,
+ cmpxchg(tmp, zr, rscratch2, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, tmp3Reg); // Sets flags for result
// Store a non-null value into the box to avoid looking like a re-entrant
// lock. The fast-path monitor unlock code checks for
// markWord::monitor_value so use markWord::unused_mark which has the
// relevant bit set, and also matches ObjectSynchronizer::enter.
mov(tmp, (address)markWord::unused_mark().value());
str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
- br(Assembler::EQ, cont); // CAS success means locking succeeded
+ br(Assembler::EQ, no_count); // CAS success means locking succeeded
- cmp(tmp3Reg, rthread);
- br(Assembler::NE, cont); // Check for recursive locking
+ cmp(tmp3Reg, rscratch2);
+ br(Assembler::NE, no_count); // Check for recursive locking
// Recursive lock case
increment(Address(disp_hdr, in_bytes(ObjectMonitor::recursions_offset()) - markWord::monitor_value), 1);
// flag == EQ still from the cmp above, checking if this is a reentrant lock
-
- bind(cont);
- // flag == EQ indicates success
- // flag == NE indicates failure
- br(Assembler::NE, no_count);
+ b(no_count);
bind(count);
- increment(Address(rthread, JavaThread::held_monitor_count_offset()));
+ inc_held_monitor_count();
bind(no_count);
+ // flag == EQ indicates success
+ // flag == NE indicates failure
}
void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Register tmpReg,
Register tmp2Reg) {
Register oop = objectReg;
Register box = boxReg;
Register disp_hdr = tmpReg;
Register tmp = tmp2Reg;
Label cont;
Label object_has_monitor;
- Label count, no_count;
+ Label no_count;
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr);
if (LockingMode == LM_LEGACY) {
// Find the lock address and load the displaced header from the stack.
ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes()));
// If the displaced header is 0, we have a recursive unlock.
cmp(disp_hdr, zr);
- br(Assembler::EQ, cont);
+ br(Assembler::EQ, no_count);
}
// Handle existing monitor.
ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
tbnz(tmp, exact_log2(markWord::monitor_value), object_has_monitor);
if (LockingMode == LM_MONITOR) {
tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
- b(cont);
+ b(no_count);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a light weight lock, this is is true if we
// see the stack address of the basicLock in the markWord of the
// object.
// Handle existing monitor.
bind(object_has_monitor);
STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
add(tmp, tmp, -(int)markWord::monitor_value); // monitor
+ // If the owner is anonymous, we need to fix it -- in an outline stub.
+ Register tmp2 = disp_hdr;
+ ldr(tmp2, Address(tmp, ObjectMonitor::owner_offset()));
+ // We cannot use tbnz here, the target might be too far away and cannot
+ // be encoded.
+ mov(rscratch1, (uint64_t)ObjectMonitor::ANONYMOUS_OWNER);
+ cmp(tmp2, rscratch1);
+ C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmp, tmp2);
+ Compile::current()->output()->add_stub(stub);
+ br(Assembler::EQ, stub->entry());
+ bind(stub->continuation());
+
ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
Label notRecursive;
cbz(disp_hdr, notRecursive);
// Recursive lock
sub(disp_hdr, disp_hdr, 1u);
str(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
cmp(disp_hdr, disp_hdr); // Sets flags for result
- b(cont);
+ b(no_count);
bind(notRecursive);
ldr(rscratch1, Address(tmp, ObjectMonitor::EntryList_offset()));
ldr(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset()));
orr(rscratch1, rscratch1, disp_hdr); // Will be 0 if both are 0.
cmp(rscratch1, zr); // Sets flags for result
- cbnz(rscratch1, cont);
+ cbnz(rscratch1, no_count);
// need a release store here
lea(tmp, Address(tmp, ObjectMonitor::owner_offset()));
stlr(zr, tmp); // set unowned
+ b(no_count);
bind(cont);
// flag == EQ indicates success
// flag == NE indicates failure
br(Assembler::NE, no_count);
- bind(count);
- decrement(Address(rthread, JavaThread::held_monitor_count_offset()));
+ dec_held_monitor_count();
bind(no_count);
}
void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register t1,
const Register t3_owner = t3;
// Compute owner address.
lea(t2_owner_addr, Address(t1_tagged_monitor, (in_bytes(ObjectMonitor::owner_offset()) - monitor_tag)));
- // CAS owner (null => current thread).
- cmpxchg(t2_owner_addr, zr, rthread, Assembler::xword, /*acquire*/ true,
+ // CAS owner (null => current thread id).
+ ldr(rscratch2, Address(rthread, JavaThread::lock_id_offset()));
+ cmpxchg(t2_owner_addr, zr, rscratch2, Assembler::xword, /*acquire*/ true,
/*release*/ false, /*weak*/ false, t3_owner);
br(Assembler::EQ, locked);
// Check if recursive.
- cmp(t3_owner, rthread);
+ cmp(t3_owner, rscratch2);
br(Assembler::NE, slow_path);
// Recursive.
increment(Address(t1_tagged_monitor, in_bytes(ObjectMonitor::recursions_offset()) - monitor_tag), 1);
}
bind(locked);
- increment(Address(rthread, JavaThread::held_monitor_count_offset()));
#ifdef ASSERT
// Check that locked label is reached with Flags == EQ.
Label flag_correct;
br(Assembler::EQ, flag_correct);
cmp(rscratch1, zr);
br(Assembler::EQ, release);
// The owner may be anonymous and we removed the last obj entry in
// the lock-stack. This loses the information about the owner.
- // Write the thread to the owner field so the runtime knows the owner.
- str(rthread, Address(t2_owner_addr));
+ // Write the thread id to the owner field so the runtime knows the owner.
+ ldr(t3_t, Address(rthread, JavaThread::lock_id_offset()));
+ str(t3_t, Address(t2_owner_addr));
b(slow_path);
bind(release);
// Set owner to null.
// Release to satisfy the JMM
stlr(zr, t2_owner_addr);
}
bind(unlocked);
- decrement(Address(rthread, JavaThread::held_monitor_count_offset()));
#ifdef ASSERT
// Check that unlocked label is reached with Flags == EQ.
Label flag_correct;
br(Assembler::EQ, flag_correct);
< prev index next >