Skip to content

Commit

Permalink
8308479: [s390x] Implement alternative fast-locking scheme
Browse files Browse the repository at this point in the history
Reviewed-by: lucy, mdoerr
  • Loading branch information
offamitkumar committed Sep 26, 2023
1 parent e2e8e8e commit 3fe6e0f
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

3 comments on commit 3fe6e0f

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

@offamitkumar
Copy link
Member Author

Choose a reason for hiding this comment

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

/backport jdk21u

@openjdk
Copy link

@openjdk openjdk bot commented on 3fe6e0f Nov 7, 2023

Choose a reason for hiding this comment

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

@offamitkumar the backport was successfully created on the branch offamitkumar-backport-3fe6e0fa in my personal fork of openjdk/jdk21u. To create a pull request with this backport targeting openjdk/jdk21u:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit 3fe6e0fa from the openjdk/jdk repository.

The commit being backported was authored by Amit Kumar on 26 Sep 2023 and was reviewed by Lutz Schmidt and Martin Doerr.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk21u:

$ git fetch https://github.com/openjdk-bots/jdk21u.git offamitkumar-backport-3fe6e0fa:offamitkumar-backport-3fe6e0fa
$ git checkout offamitkumar-backport-3fe6e0fa
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk21u.git offamitkumar-backport-3fe6e0fa

Please sign in to comment.