< prev index next > src/hotspot/cpu/aarch64/aarch64.ad
Print this page
if (C->output()->need_stack_bang(bangsize))
__ generate_stack_overflow_check(bangsize);
__ build_frame(framesize);
+ int max_monitors = C->method() != NULL ? C->max_monitors() : 0;
+ if (UseFastLocking && max_monitors > 0) {
+ C2CheckLockStackStub* stub = new (C->comp_arena()) C2CheckLockStackStub();
+ C->output()->add_stub(stub);
+ __ ldr(r9, Address(rthread, JavaThread::lock_stack_current_offset()));
+ __ ldr(r10, Address(rthread, JavaThread::lock_stack_limit_offset()));
+ __ add(r9, r9, max_monitors * oopSize);
+ __ cmp(r9, r10);
+ __ br(Assembler::GE, stub->entry());
+ __ bind(stub->continuation());
+ }
+
if (C->stub_function() == NULL) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
// Dummy labels for just measuring the code size
Label dummy_slow_path;
Register box = as_Register($box$$reg);
Register disp_hdr = as_Register($tmp$$reg);
Register tmp = as_Register($tmp2$$reg);
Label cont;
Label object_has_monitor;
- Label no_count;
+ Label count, no_count;
assert_different_registers(oop, box, tmp, disp_hdr);
// Load markWord from object into displaced_header.
__ ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
// Check for existing monitor
__ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
if (!UseHeavyMonitors) {
- // Set tmp to be (markWord of object | UNLOCK_VALUE).
- __ orr(tmp, disp_hdr, markWord::unlocked_value);
-
- // Initialize the box. (Must happen before we update the object mark!)
- __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
-
- // 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);
-
- 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
+ if (UseFastLocking) {
+ __ fast_lock(oop, disp_hdr, tmp, rscratch1, no_count, false);
- // Check if the owner is self by comparing the value in the
- // markWord of object (disp_hdr) with the stack pointer.
- __ mov(rscratch1, sp);
- __ sub(disp_hdr, disp_hdr, rscratch1);
- __ 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()));
+ // Indicate success at cont.
+ __ cmp(oop, oop);
+ __ b(count);
+ } else {
+ // Set tmp to be (markWord of object | UNLOCK_VALUE).
+ __ orr(tmp, disp_hdr, markWord::unlocked_value);
+
+ // Initialize the box. (Must happen before we update the object mark!)
+ __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
+
+ // 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);
+
+ 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
+
+ // Check if the owner is self by comparing the value in the
+ // markWord of object (disp_hdr) with the stack pointer.
+ __ mov(rscratch1, sp);
+ __ sub(disp_hdr, disp_hdr, rscratch1);
+ __ 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);
+ }
} else {
__ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
+ __ b(cont);
}
- __ b(cont);
// Handle existing monitor.
__ bind(object_has_monitor);
// The object's monitor m is unlocked iff m->owner == NULL,
// Try to CAS m->owner from NULL to current thread.
__ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes()-markWord::monitor_value));
__ cmpxchg(tmp, zr, rthread, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, rscratch1); // 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()));
-
+ if (!UseFastLocking) {
+ // 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
__ cmp(rscratch1, rthread);
__ br(Assembler::NE, cont); // Check for recursive locking
__ bind(cont);
// flag == EQ indicates success
// flag == NE indicates failure
__ br(Assembler::NE, no_count);
+ __ bind(count);
__ increment(Address(rthread, JavaThread::held_monitor_count_offset()));
__ bind(no_count);
%}
Register box = as_Register($box$$reg);
Register disp_hdr = as_Register($tmp$$reg);
Register tmp = as_Register($tmp2$$reg);
Label cont;
Label object_has_monitor;
- Label no_count;
+ Label count, no_count;
assert_different_registers(oop, box, tmp, disp_hdr);
- if (!UseHeavyMonitors) {
+ if (!UseHeavyMonitors && !UseFastLocking) {
// 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);
// Handle existing monitor.
__ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
__ tbnz(tmp, exact_log2(markWord::monitor_value), object_has_monitor);
if (!UseHeavyMonitors) {
- // 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.
+ if (UseFastLocking) {
+ __ fast_unlock(oop, tmp, box, disp_hdr, no_count);
- __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false,
- /*release*/ true, /*weak*/ false, tmp);
+ // Indicate success at cont.
+ __ cmp(oop, oop);
+ __ b(count);
+ } else {
+ // 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.
+
+ __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false,
+ /*release*/ true, /*weak*/ false, tmp);
+ __ b(cont);
+ }
} else {
__ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
+ __ b(cont);
}
- __ b(cont);
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// Handle existing monitor.
__ bind(object_has_monitor);
STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
__ add(tmp, tmp, -(int)markWord::monitor_value); // monitor
+
+ if (UseFastLocking) {
+ // 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_in_bytes()));
+ // We cannot use tbnz here, the target might be too far away and cannot
+ // be encoded.
+ __ tst(tmp2, (uint64_t)(intptr_t) ANONYMOUS_OWNER);
+ C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmp, tmp2);
+ Compile::current()->output()->add_stub(stub);
+ __ br(Assembler::NE, stub->entry());
+ __ bind(stub->continuation());
+ }
+
__ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));
Label notRecursive;
__ cbz(disp_hdr, notRecursive);
__ 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()));
__ bind(no_count);
%}
// Load Narrow Klass Pointer
instruct loadNKlass(iRegNNoSp dst, memory4 mem)
%{
match(Set dst (LoadNKlass mem));
- predicate(!needs_acquiring_load(n));
+ predicate(!needs_acquiring_load(n) && !UseCompactObjectHeaders);
ins_cost(4 * INSN_COST);
format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
ins_encode(aarch64_enc_ldrw(dst, mem));
ins_pipe(iload_reg_mem);
%}
+ instruct loadNKlassLilliput(iRegNNoSp dst, memory4 mem, rFlagsReg cr)
+ %{
+ match(Set dst (LoadNKlass mem));
+ effect(TEMP_DEF dst, KILL cr);
+ predicate(!needs_acquiring_load(n) && UseCompactObjectHeaders);
+
+ ins_cost(4 * INSN_COST);
+ format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
+ ins_encode %{
+ assert($mem$$disp == oopDesc::klass_offset_in_bytes(), "expect correct offset");
+ assert($mem$$index$$Register == noreg, "expect no index");
+ Register dst = $dst$$Register;
+ Register obj = $mem$$base$$Register;
+ C2LoadNKlassStub* stub = new (Compile::current()->comp_arena()) C2LoadNKlassStub(dst);
+ Compile::current()->output()->add_stub(stub);
+ __ ldr(dst, Address(obj, oopDesc::mark_offset_in_bytes()));
+ // NOTE: We can't use tbnz here, because the target is sometimes too far away
+ // and cannot be encoded.
+ __ tst(dst, markWord::monitor_value);
+ __ br(Assembler::NE, stub->entry());
+ __ bind(stub->continuation());
+ __ lsr(dst, dst, markWord::klass_shift);
+ %}
+ ins_pipe(pipe_slow);
+ %}
+
// Load Float
instruct loadF(vRegF dst, memory4 mem)
%{
match(Set dst (LoadF mem));
predicate(!needs_acquiring_load(n));
< prev index next >