Skip to content

Commit

Permalink
8308479: [s390x] Implement alternative fast-locking scheme
Browse files Browse the repository at this point in the history
Backport-of: 3fe6e0faca78e8106e33a3a53de78f8864be92b7
  • Loading branch information
offamitkumar authored and TheRealMDoerr committed Nov 9, 2023
1 parent 5cb041e commit 54fbd4b
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 134 deletions.
73 changes: 41 additions & 32 deletions src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -83,96 +83,105 @@ void C1_MacroAssembler::verified_entry(bool breakAtEntry) {
if (breakAtEntry) z_illtrap(0xC1);
}

void C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(hdr, obj, disp_hdr);

verify_oop(obj, FILE_AND_LINE);
const Register tmp = Z_R1_scratch;

assert_different_registers(Rmark, Roop, Rbox, tmp);

verify_oop(Roop, FILE_AND_LINE);

// Load object header.
z_lg(hdr, Address(obj, hdr_offset));
z_lg(Rmark, Address(Roop, hdr_offset));

// Save object being locked into the BasicObjectLock...
z_stg(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
z_stg(Roop, Address(Rbox, BasicObjectLock::obj_offset()));

if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(Z_R1_scratch, obj);
testbit(Address(Z_R1_scratch, Klass::access_flags_offset()), exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS));
load_klass(tmp, Roop);
testbit(Address(tmp, Klass::access_flags_offset()), exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS));
z_btrue(slow_case);
}

assert(LockingMode != LM_MONITOR, "LM_MONITOR is already handled, by emit_lock()");

if (LockingMode == LM_LIGHTWEIGHT) {
Unimplemented();
fast_lock(Roop, Rmark, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
NearLabel done;
// and mark it as unlocked.
z_oill(hdr, markWord::unlocked_value);
z_oill(Rmark, markWord::unlocked_value);
// Save unlocked object header into the displaced header location on the stack.
z_stg(hdr, Address(disp_hdr, (intptr_t) 0));
z_stg(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
// Test if object header is still the same (i.e. unlocked), and if so, store the
// displaced header address in the object header. If it is not the same, get the
// object header instead.
z_csg(hdr, disp_hdr, hdr_offset, obj);
z_csg(Rmark, Rbox, hdr_offset, Roop);
// If the object header was the same, we're done.
branch_optimized(Assembler::bcondEqual, done);
// If the object header was not the same, it is now in the hdr register.
// If the object header was not the same, it is now in the Rmark register.
// => Test if it is a stack pointer into the same stack (recursive locking), i.e.:
//
// 1) (hdr & markWord::lock_mask_in_place) == 0
// 2) rsp <= hdr
// 3) hdr <= rsp + page_size
// 1) (Rmark & markWord::lock_mask_in_place) == 0
// 2) rsp <= Rmark
// 3) Rmark <= rsp + page_size
//
// These 3 tests can be done by evaluating the following expression:
//
// (hdr - Z_SP) & (~(page_size-1) | markWord::lock_mask_in_place)
// (Rmark - Z_SP) & (~(page_size-1) | markWord::lock_mask_in_place)
//
// assuming both the stack pointer and page_size have their least
// significant 2 bits cleared and page_size is a power of 2
z_sgr(hdr, Z_SP);
z_sgr(Rmark, Z_SP);

load_const_optimized(Z_R0_scratch, (~(os::vm_page_size() - 1) | markWord::lock_mask_in_place));
z_ngr(hdr, Z_R0_scratch); // AND sets CC (result eq/ne 0).
z_ngr(Rmark, Z_R0_scratch); // AND sets CC (result eq/ne 0).
// For recursive locking, the result is zero. => Save it in the displaced header
// location (null in the displaced hdr location indicates recursive locking).
z_stg(hdr, Address(disp_hdr, (intptr_t) 0));
// location (null in the displaced Rmark location indicates recursive locking).
z_stg(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
// Otherwise we don't care about the result and handle locking via runtime call.
branch_optimized(Assembler::bcondNotZero, slow_case);
// done
bind(done);
}
}

void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(hdr, obj, disp_hdr);

assert_different_registers(Rmark, Roop, Rbox);

NearLabel done;

if (LockingMode != LM_LIGHTWEIGHT) {
// Load displaced header.
z_ltg(hdr, Address(disp_hdr, (intptr_t) 0));
// If the loaded hdr is null we had recursive locking, and we are done.
z_ltg(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
// If the loaded Rmark is null we had recursive locking, and we are done.
z_bre(done);
}

// Load object.
z_lg(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
verify_oop(obj, FILE_AND_LINE);
z_lg(Roop, Address(Rbox, BasicObjectLock::obj_offset()));
verify_oop(Roop, FILE_AND_LINE);

if (LockingMode == LM_LIGHTWEIGHT) {
Unimplemented();
} else {
const Register tmp = Z_R1_scratch;
z_lg(Rmark, Address(Roop, hdr_offset));
z_lgr(tmp, Rmark);
z_nill(tmp, markWord::monitor_value);
z_brnz(slow_case);
fast_unlock(Roop, Rmark, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object. If the object header is not pointing to
// the displaced header, get the object header instead.
z_csg(disp_hdr, hdr, hdr_offset, obj);
z_csg(Rbox, Rmark, hdr_offset, Roop);
// If the object header was not pointing to the displaced header,
// we do unlocking via runtime call.
branch_optimized(Assembler::bcondNotEqual, slow_case);
// done
}
// done
bind(done);
}

Expand Down
21 changes: 11 additions & 10 deletions src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -41,17 +41,18 @@
void initialize_body(Register objectFields, Register len_in_bytes, Register Rzero);

// locking
// hdr : Used to hold locked markWord to be CASed into obj, contents destroyed.
// obj : Must point to the object to lock, contents preserved.
// disp_hdr: Must point to the displaced header location, contents preserved.
// Returns code offset at which to add null check debug information.
void lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case);
// Rmark : Used to hold locked markWord to be CASed into obj, contents destroyed.
// Roop : Must point to the object to lock, contents preserved.
// Rbox : Must point to the displaced header location, contents preserved.
// Z_R1_scratch : Used as temp and will be killed
void lock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case);

// unlocking
// hdr : Used to hold original markWord to be CASed back into obj, contents destroyed.
// obj : Must point to the object to lock, contents preserved.
// disp_hdr: Must point to the displaced header location, contents destroyed.
void unlock_object(Register hdr, Register obj, Register lock, Label& slow_case);
// Rmark : Used to hold original markWord to be CASed back into obj, contents destroyed.
// Roop : Must point to the object to lock, contents preserved.
// Rbox : Must point to the displaced header location, contents destroyed.
// Z_R1_scratch : Used as temp and will be killed
void unlock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case);

void initialize_object(
Register obj, // result: Pointer to object after successful allocation.
Expand Down
Loading

1 comment on commit 54fbd4b

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.