Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions make/RunTests.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,11 @@ define SetupRunJtregTestBody
$1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$($1_JTREG_PROBLEM_LIST))
endif

# Add more Lilliput-specific ProblemLists when UCOH is enabled
ifneq ($$(findstring -XX:+UseCompactObjectHeaders, $$(TEST_OPTS)), )
JTREG_EXTRA_PROBLEM_LISTS += $(TOPDIR)/test/hotspot/jtreg/ProblemList-lilliput.txt
endif

ifneq ($$(JTREG_EXTRA_PROBLEM_LISTS), )
# Accept both absolute paths as well as relative to the current test root.
$1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \
Expand Down
229 changes: 60 additions & 169 deletions src/hotspot/cpu/aarch64/aarch64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -1986,7 +1986,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Label dummy_label;
Label* code_stub = &dummy_label;
if (!C->output()->in_scratch_emit_size()) {
code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset());
C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset());
C->output()->add_stub(stub);
code_stub = &stub->entry();
}
__ relocate(relocInfo::poll_return_type);
__ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */);
Expand Down Expand Up @@ -3799,166 +3801,6 @@ encode %{
__ br(target_reg);
%}

enc_class aarch64_enc_fast_lock(iRegP object, iRegP box, iRegP tmp, iRegP tmp2) %{
C2_MacroAssembler _masm(&cbuf);
Register oop = as_Register($object$$reg);
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 cas_failed;

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()));

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);
}

if (UseBiasedLocking && !UseOptoBiasInlining) {
__ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont);
}

// Check for existing monitor
__ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);

// 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

__ bind(cas_failed);
// We did not see an unlocked object so try the fast recursive case.

// 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);

// Handle existing monitor.
__ bind(object_has_monitor);

// The object's monitor m is unlocked iff m->owner == NULL,
// otherwise m->owner may contain a thread or a stack address.
//
// 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()));

__ br(Assembler::EQ, cont); // CAS success means locking succeeded

__ cmp(rscratch1, rthread);
__ br(Assembler::NE, cont); // Check for recursive locking

// Recursive lock case
__ increment(Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - 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
%}

enc_class aarch64_enc_fast_unlock(iRegP object, iRegP box, iRegP tmp, iRegP tmp2) %{
C2_MacroAssembler _masm(&cbuf);
Register oop = as_Register($object$$reg);
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;

assert_different_registers(oop, box, tmp, disp_hdr);

if (UseBiasedLocking && !UseOptoBiasInlining) {
__ biased_locking_exit(oop, tmp, cont);
}

// 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);

// Handle existing monitor.
__ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
__ tbnz(tmp, exact_log2(markWord::monitor_value), object_has_monitor);

// 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);

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
__ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));

Label notRecursive;
__ cbz(disp_hdr, notRecursive);

// Recursive lock
__ sub(disp_hdr, disp_hdr, 1u);
__ str(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes()));
__ cmp(disp_hdr, disp_hdr); // Sets flags for result
__ b(cont);

__ bind(notRecursive);
__ ldr(rscratch1, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes()));
__ ldr(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes()));
__ orr(rscratch1, rscratch1, disp_hdr); // Will be 0 if both are 0.
__ cmp(rscratch1, zr); // Sets flags for result
__ cbnz(rscratch1, cont);
// need a release store here
__ lea(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes()));
__ stlr(zr, tmp); // set unowned

__ bind(cont);
// flag == EQ indicates success
// flag == NE indicates failure
%}

%}

//----------FRAME--------------------------------------------------------------
Expand Down Expand Up @@ -7439,7 +7281,7 @@ instruct loadKlass(iRegPNoSp dst, memory8 mem)
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" %}
Expand All @@ -7449,6 +7291,20 @@ instruct loadNKlass(iRegNNoSp dst, memory4 mem)
ins_pipe(iload_reg_mem);
%}

instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory4 mem, rFlagsReg cr)
%{
match(Set dst (LoadNKlass mem));
effect(KILL cr);
predicate(!needs_acquiring_load(n) && UseCompactObjectHeaders);

ins_cost(4 * INSN_COST);
format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
ins_encode %{
__ load_nklass_compact($dst$$Register, $mem$$base$$Register, $mem$$index$$Register, $mem$$scale, $mem$$disp);
%}
ins_pipe(pipe_slow);
%}

// Load Float
instruct loadF(vRegF dst, memory4 mem)
%{
Expand Down Expand Up @@ -16409,34 +16265,69 @@ instruct branchLoopEndU(cmpOpU cmp, rFlagsRegU cr, label lbl)
// ============================================================================
// inlined locking and unlocking

instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP tmp2);
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);

// TODO
// identify correct cost
ins_cost(5 * INSN_COST);
format %{ "fastlock $object,$box\t! kills $tmp,$tmp2" %}
format %{ "fastlock $object,$box\t! kills $tmp,$tmp2,$tmp3" %}

ins_encode(aarch64_enc_fast_lock(object, box, tmp, tmp2));
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register, $tmp3$$Register);
%}

ins_pipe(pipe_serial);
%}

instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
%{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, TEMP tmp2);

ins_cost(5 * INSN_COST);
format %{ "fastunlock $object,$box\t! kills $tmp, $tmp2" %}

ins_encode(aarch64_enc_fast_unlock(object, box, tmp, tmp2));
ins_encode %{
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register);
%}

ins_pipe(pipe_serial);
%}

instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
%{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP tmp2);

ins_cost(5 * INSN_COST);
format %{ "fastlock $object,$box\t! kills $tmp,$tmp2" %}

ins_encode %{
__ fast_lock_lightweight($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register);
%}

ins_pipe(pipe_serial);
%}

instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
%{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, TEMP tmp2);

ins_cost(5 * INSN_COST);
format %{ "fastunlock $object,$box\t! kills $tmp, $tmp2" %}

ins_encode %{
__ fast_unlock_lightweight($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register);
%}

ins_pipe(pipe_serial);
%}

// ============================================================================
// Safepoint Instructions
Expand Down
8 changes: 8 additions & 0 deletions src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "c1/c1_Runtime1.hpp"
#include "classfile/javaClasses.hpp"
#include "nativeInst_aarch64.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/sharedRuntime.hpp"
#include "vmreg_aarch64.inline.hpp"

Expand Down Expand Up @@ -253,6 +254,13 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) {
__ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id)));
}

void LoadKlassStub::emit_code(LIR_Assembler* ce) {
assert(UseCompactObjectHeaders, "Only use with compact object headers");
__ bind(_entry);
Register d = _result->as_register();
__ ldr(d, Address(d, OM_OFFSET_NO_MONITOR_VALUE_TAG(header)));
__ b(_continuation);
}

// Implementation of patching:
// - Copy the code at given offset to an inlined buffer (first the bytes, then the number of bytes)
Expand Down
Loading
Loading