Skip to content

Commit 47df145

Browse files
committed
8310513: [s390x] Intrinsify recursive ObjectMonitor locking
Reviewed-by: lucy, mdoerr
1 parent b81b86d commit 47df145

File tree

1 file changed

+64
-46
lines changed

1 file changed

+64
-46
lines changed

src/hotspot/cpu/s390/macroAssembler_s390.cpp

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2016, 2023 SAP SE. All rights reserved.
3+
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -3196,28 +3196,32 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
31963196
Register temp = temp2;
31973197
NearLabel done, object_has_monitor;
31983198

3199+
const int hdr_offset = oopDesc::mark_offset_in_bytes();
3200+
3201+
assert_different_registers(temp1, temp2, oop, box);
3202+
31993203
BLOCK_COMMENT("compiler_fast_lock_object {");
32003204

32013205
// Load markWord from oop into mark.
3202-
z_lg(displacedHeader, 0, oop);
3206+
z_lg(displacedHeader, hdr_offset, oop);
32033207

32043208
if (DiagnoseSyncOnValueBasedClasses != 0) {
3205-
load_klass(Z_R1_scratch, oop);
3206-
z_l(Z_R1_scratch, Address(Z_R1_scratch, Klass::access_flags_offset()));
3209+
load_klass(temp, oop);
3210+
z_l(temp, Address(temp, Klass::access_flags_offset()));
32073211
assert((JVM_ACC_IS_VALUE_BASED_CLASS & 0xFFFF) == 0, "or change following instruction");
3208-
z_nilh(Z_R1_scratch, JVM_ACC_IS_VALUE_BASED_CLASS >> 16);
3212+
z_nilh(temp, JVM_ACC_IS_VALUE_BASED_CLASS >> 16);
32093213
z_brne(done);
32103214
}
32113215

32123216
// Handle existing monitor.
32133217
// The object has an existing monitor iff (mark & monitor_value) != 0.
32143218
guarantee(Immediate::is_uimm16(markWord::monitor_value), "must be half-word");
3215-
z_lgr(temp, displacedHeader);
3216-
z_nill(temp, markWord::monitor_value);
3217-
z_brne(object_has_monitor);
3219+
z_tmll(displacedHeader, markWord::monitor_value);
3220+
z_brnaz(object_has_monitor);
32183221

32193222
if (LockingMode == LM_MONITOR) {
32203223
// Set NE to indicate 'failure' -> take slow-path
3224+
// From loading the markWord, we know that oop != nullptr
32213225
z_ltgr(oop, oop);
32223226
z_bru(done);
32233227
} else if (LockingMode == LM_LEGACY) {
@@ -3229,23 +3233,24 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
32293233
// Initialize the box (must happen before we update the object mark).
32303234
z_stg(displacedHeader, BasicLock::displaced_header_offset_in_bytes(), box);
32313235

3232-
// Memory Fence (in cmpxchgd)
3233-
// Compare object markWord with mark and if equal exchange scratch1 with object markWord.
3234-
3235-
// If the compare-and-swap succeeded, then we found an unlocked object and we
3236-
// have now locked it.
3237-
z_csg(displacedHeader, box, 0, oop);
3236+
// Compare object markWord with mark and if equal, exchange box with object markWork.
3237+
// If the compare-and-swap succeeds, then we found an unlocked object and have now locked it.
3238+
z_csg(displacedHeader, box, hdr_offset, oop);
32383239
assert(currentHeader == displacedHeader, "must be same register"); // Identified two registers from z/Architecture.
32393240
z_bre(done);
32403241

3241-
// We did not see an unlocked object so try the fast recursive case.
3242-
3242+
// We did not see an unlocked object
3243+
// currentHeader contains what is currently stored in the oop's markWord.
3244+
// We might have a recursive case. Verify by checking if the owner is self.
3245+
// To do so, compare the value in the markWord (currentHeader) with the stack pointer.
32433246
z_sgr(currentHeader, Z_SP);
32443247
load_const_optimized(temp, (~(os::vm_page_size() - 1) | markWord::lock_mask_in_place));
32453248

32463249
z_ngr(currentHeader, temp);
3247-
// z_brne(done);
3248-
// z_release();
3250+
3251+
// result zero: owner is self -> recursive lock. Indicate that by storing 0 in the box.
3252+
// result not-zero: attempt failed. We don't hold the lock -> go for slow case.
3253+
32493254
z_stg(currentHeader/*==0 or not 0*/, BasicLock::displaced_header_offset_in_bytes(), box);
32503255

32513256
z_bru(done);
@@ -3255,28 +3260,34 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
32553260
z_bru(done);
32563261
}
32573262

3263+
bind(object_has_monitor);
3264+
32583265
Register zero = temp;
32593266
Register monitor_tagged = displacedHeader; // Tagged with markWord::monitor_value.
3260-
bind(object_has_monitor);
32613267
// The object's monitor m is unlocked iff m->owner is null,
32623268
// otherwise m->owner may contain a thread or a stack address.
3263-
//
3269+
32643270
// Try to CAS m->owner from null to current thread.
3265-
z_lghi(zero, 0);
32663271
// If m->owner is null, then csg succeeds and sets m->owner=THREAD and CR=EQ.
3272+
// Otherwise, register zero is filled with the current owner.
3273+
z_lghi(zero, 0);
32673274
z_csg(zero, Z_thread, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), monitor_tagged);
32683275
if (LockingMode != LM_LIGHTWEIGHT) {
32693276
// Store a non-null value into the box.
32703277
z_stg(box, BasicLock::displaced_header_offset_in_bytes(), box);
32713278
}
3272-
#ifdef ASSERT
3273-
z_brne(done);
3274-
// We've acquired the monitor, check some invariants.
3275-
// Invariant 1: _recursions should be 0.
3276-
asm_assert_mem8_is_zero(OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions), monitor_tagged,
3277-
"monitor->_recursions should be 0", -1);
3278-
z_ltgr(zero, zero); // Set CR=EQ.
3279-
#endif
3279+
3280+
z_bre(done); // acquired the lock for the first time.
3281+
3282+
BLOCK_COMMENT("fast_path_recursive_lock {");
3283+
// Check if we are already the owner (recursive lock)
3284+
z_cgr(Z_thread, zero); // owner is stored in zero by "z_csg" above
3285+
z_brne(done); // not a recursive lock
3286+
3287+
// Current thread already owns the lock. Just increment recursion count.
3288+
z_agsi(Address(monitor_tagged, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 1ll);
3289+
z_cgr(zero, zero); // set the CC to EQUAL
3290+
BLOCK_COMMENT("} fast_path_recursive_lock");
32803291
bind(done);
32813292

32823293
BLOCK_COMMENT("} compiler_fast_lock_object");
@@ -3289,11 +3300,12 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
32893300
Register displacedHeader = temp1;
32903301
Register currentHeader = temp2;
32913302
Register temp = temp1;
3292-
Register monitor = temp2;
32933303

32943304
const int hdr_offset = oopDesc::mark_offset_in_bytes();
32953305

3296-
Label done, object_has_monitor;
3306+
assert_different_registers(temp1, temp2, oop, box);
3307+
3308+
Label done, object_has_monitor, not_recursive;
32973309

32983310
BLOCK_COMMENT("compiler_fast_unlock_object {");
32993311

@@ -3308,30 +3320,25 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
33083320
// The object has an existing monitor iff (mark & monitor_value) != 0.
33093321
z_lg(currentHeader, hdr_offset, oop);
33103322
guarantee(Immediate::is_uimm16(markWord::monitor_value), "must be half-word");
3311-
if (LockingMode == LM_LIGHTWEIGHT) {
3312-
z_lgr(temp, currentHeader);
3313-
}
3314-
z_nill(currentHeader, markWord::monitor_value);
3315-
z_brne(object_has_monitor);
3323+
3324+
z_tmll(currentHeader, markWord::monitor_value);
3325+
z_brnaz(object_has_monitor);
33163326

33173327
if (LockingMode == LM_MONITOR) {
33183328
// Set NE to indicate 'failure' -> take slow-path
33193329
z_ltgr(oop, oop);
33203330
z_bru(done);
33213331
} else if (LockingMode == LM_LEGACY) {
3322-
// Check if it is still a light weight lock, this is true if we see
3332+
// Check if it is still a lightweight lock, this is true if we see
33233333
// the stack address of the basicLock in the markWord of the object
33243334
// copy box to currentHeader such that csg does not kill it.
33253335
z_lgr(currentHeader, box);
3326-
z_csg(currentHeader, displacedHeader, 0, oop);
3336+
z_csg(currentHeader, displacedHeader, hdr_offset, oop);
33273337
z_bru(done); // csg sets CR as desired.
33283338
} else {
33293339
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
33303340

3331-
// don't load currentHead again from stack-top after monitor check, as it is possible
3332-
// some other thread modified it.
3333-
// currentHeader is altered, but it's contents are copied in temp as well
3334-
lightweight_unlock(oop, temp, currentHeader, done);
3341+
lightweight_unlock(oop, currentHeader, displacedHeader, done);
33353342
z_bru(done);
33363343
}
33373344

@@ -3340,11 +3347,22 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
33403347

33413348
// Handle existing monitor.
33423349
bind(object_has_monitor);
3343-
z_lg(currentHeader, hdr_offset, oop); // CurrentHeader is tagged with monitor_value set.
3344-
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
3345-
z_brne(done);
3346-
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
3350+
3351+
z_cg(Z_thread, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
33473352
z_brne(done);
3353+
3354+
BLOCK_COMMENT("fast_path_recursive_unlock {");
3355+
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
3356+
z_bre(not_recursive); // if 0 then jump, it's not recursive locking
3357+
3358+
// Recursive inflated unlock
3359+
z_agsi(Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), -1ll);
3360+
z_cgr(currentHeader, currentHeader); // set the CC to EQUAL
3361+
BLOCK_COMMENT("} fast_path_recursive_unlock");
3362+
z_bru(done);
3363+
3364+
bind(not_recursive);
3365+
33483366
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
33493367
z_brne(done);
33503368
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));

0 commit comments

Comments
 (0)