1
1
/*
2
2
* Copyright (c) 2016, 2023, 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.
4
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
5
*
6
6
* This code is free software; you can redistribute it and/or modify it
@@ -3149,28 +3149,32 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
3149
3149
Register temp = temp2;
3150
3150
NearLabel done, object_has_monitor;
3151
3151
3152
+ const int hdr_offset = oopDesc::mark_offset_in_bytes ();
3153
+
3154
+ assert_different_registers (temp1, temp2, oop, box);
3155
+
3152
3156
BLOCK_COMMENT (" compiler_fast_lock_object {" );
3153
3157
3154
3158
// Load markWord from oop into mark.
3155
- z_lg (displacedHeader, 0 , oop);
3159
+ z_lg (displacedHeader, hdr_offset , oop);
3156
3160
3157
3161
if (DiagnoseSyncOnValueBasedClasses != 0 ) {
3158
- load_klass (Z_R1_scratch , oop);
3159
- z_l (Z_R1_scratch , Address (Z_R1_scratch , Klass::access_flags_offset ()));
3162
+ load_klass (temp , oop);
3163
+ z_l (temp , Address (temp , Klass::access_flags_offset ()));
3160
3164
assert ((JVM_ACC_IS_VALUE_BASED_CLASS & 0xFFFF ) == 0 , " or change following instruction" );
3161
- z_nilh (Z_R1_scratch , JVM_ACC_IS_VALUE_BASED_CLASS >> 16 );
3165
+ z_nilh (temp , JVM_ACC_IS_VALUE_BASED_CLASS >> 16 );
3162
3166
z_brne (done);
3163
3167
}
3164
3168
3165
3169
// Handle existing monitor.
3166
3170
// The object has an existing monitor iff (mark & monitor_value) != 0.
3167
3171
guarantee (Immediate::is_uimm16 (markWord::monitor_value), " must be half-word" );
3168
- z_lgr (temp, displacedHeader);
3169
- z_nill (temp, markWord::monitor_value);
3170
- z_brne (object_has_monitor);
3172
+ z_tmll (displacedHeader, markWord::monitor_value);
3173
+ z_brnaz (object_has_monitor);
3171
3174
3172
3175
if (LockingMode == LM_MONITOR) {
3173
3176
// Set NE to indicate 'failure' -> take slow-path
3177
+ // From loading the markWord, we know that oop != nullptr
3174
3178
z_ltgr (oop, oop);
3175
3179
z_bru (done);
3176
3180
} else if (LockingMode == LM_LEGACY) {
@@ -3182,23 +3186,24 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
3182
3186
// Initialize the box (must happen before we update the object mark).
3183
3187
z_stg (displacedHeader, BasicLock::displaced_header_offset_in_bytes (), box);
3184
3188
3185
- // Memory Fence (in cmpxchgd)
3186
- // Compare object markWord with mark and if equal exchange scratch1 with object markWord.
3187
-
3188
- // If the compare-and-swap succeeded, then we found an unlocked object and we
3189
- // have now locked it.
3190
- z_csg (displacedHeader, box, 0 , oop);
3189
+ // Compare object markWord with mark and if equal, exchange box with object markWork.
3190
+ // If the compare-and-swap succeeds, then we found an unlocked object and have now locked it.
3191
+ z_csg (displacedHeader, box, hdr_offset, oop);
3191
3192
assert (currentHeader == displacedHeader, " must be same register" ); // Identified two registers from z/Architecture.
3192
3193
z_bre (done);
3193
3194
3194
- // We did not see an unlocked object so try the fast recursive case.
3195
-
3195
+ // We did not see an unlocked object
3196
+ // currentHeader contains what is currently stored in the oop's markWord.
3197
+ // We might have a recursive case. Verify by checking if the owner is self.
3198
+ // To do so, compare the value in the markWord (currentHeader) with the stack pointer.
3196
3199
z_sgr (currentHeader, Z_SP);
3197
3200
load_const_optimized (temp, (~(os::vm_page_size () - 1 ) | markWord::lock_mask_in_place));
3198
3201
3199
3202
z_ngr (currentHeader, temp);
3200
- // z_brne(done);
3201
- // z_release();
3203
+
3204
+ // result zero: owner is self -> recursive lock. Indicate that by storing 0 in the box.
3205
+ // result not-zero: attempt failed. We don't hold the lock -> go for slow case.
3206
+
3202
3207
z_stg (currentHeader/* ==0 or not 0*/ , BasicLock::displaced_header_offset_in_bytes (), box);
3203
3208
3204
3209
z_bru (done);
@@ -3208,28 +3213,34 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
3208
3213
z_bru (done);
3209
3214
}
3210
3215
3216
+ bind (object_has_monitor);
3217
+
3211
3218
Register zero = temp;
3212
3219
Register monitor_tagged = displacedHeader; // Tagged with markWord::monitor_value.
3213
- bind (object_has_monitor);
3214
3220
// The object's monitor m is unlocked iff m->owner is null,
3215
3221
// otherwise m->owner may contain a thread or a stack address.
3216
- //
3222
+
3217
3223
// Try to CAS m->owner from null to current thread.
3218
- z_lghi (zero, 0 );
3219
3224
// If m->owner is null, then csg succeeds and sets m->owner=THREAD and CR=EQ.
3225
+ // Otherwise, register zero is filled with the current owner.
3226
+ z_lghi (zero, 0 );
3220
3227
z_csg (zero, Z_thread, OM_OFFSET_NO_MONITOR_VALUE_TAG (owner), monitor_tagged);
3221
3228
if (LockingMode != LM_LIGHTWEIGHT) {
3222
3229
// Store a non-null value into the box.
3223
3230
z_stg (box, BasicLock::displaced_header_offset_in_bytes (), box);
3224
3231
}
3225
- #ifdef ASSERT
3226
- z_brne (done);
3227
- // We've acquired the monitor, check some invariants.
3228
- // Invariant 1: _recursions should be 0.
3229
- asm_assert_mem8_is_zero (OM_OFFSET_NO_MONITOR_VALUE_TAG (recursions), monitor_tagged,
3230
- " monitor->_recursions should be 0" , -1 );
3231
- z_ltgr (zero, zero); // Set CR=EQ.
3232
- #endif
3232
+
3233
+ z_bre (done); // acquired the lock for the first time.
3234
+
3235
+ BLOCK_COMMENT (" fast_path_recursive_lock {" );
3236
+ // Check if we are already the owner (recursive lock)
3237
+ z_cgr (Z_thread, zero); // owner is stored in zero by "z_csg" above
3238
+ z_brne (done); // not a recursive lock
3239
+
3240
+ // Current thread already owns the lock. Just increment recursion count.
3241
+ z_agsi (Address (monitor_tagged, OM_OFFSET_NO_MONITOR_VALUE_TAG (recursions)), 1ll );
3242
+ z_cgr (zero, zero); // set the CC to EQUAL
3243
+ BLOCK_COMMENT (" } fast_path_recursive_lock" );
3233
3244
bind (done);
3234
3245
3235
3246
BLOCK_COMMENT (" } compiler_fast_lock_object" );
@@ -3242,11 +3253,12 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
3242
3253
Register displacedHeader = temp1;
3243
3254
Register currentHeader = temp2;
3244
3255
Register temp = temp1;
3245
- Register monitor = temp2;
3246
3256
3247
3257
const int hdr_offset = oopDesc::mark_offset_in_bytes ();
3248
3258
3249
- Label done, object_has_monitor;
3259
+ assert_different_registers (temp1, temp2, oop, box);
3260
+
3261
+ Label done, object_has_monitor, not_recursive;
3250
3262
3251
3263
BLOCK_COMMENT (" compiler_fast_unlock_object {" );
3252
3264
@@ -3261,30 +3273,25 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
3261
3273
// The object has an existing monitor iff (mark & monitor_value) != 0.
3262
3274
z_lg (currentHeader, hdr_offset, oop);
3263
3275
guarantee (Immediate::is_uimm16 (markWord::monitor_value), " must be half-word" );
3264
- if (LockingMode == LM_LIGHTWEIGHT) {
3265
- z_lgr (temp, currentHeader);
3266
- }
3267
- z_nill (currentHeader, markWord::monitor_value);
3268
- z_brne (object_has_monitor);
3276
+
3277
+ z_tmll (currentHeader, markWord::monitor_value);
3278
+ z_brnaz (object_has_monitor);
3269
3279
3270
3280
if (LockingMode == LM_MONITOR) {
3271
3281
// Set NE to indicate 'failure' -> take slow-path
3272
3282
z_ltgr (oop, oop);
3273
3283
z_bru (done);
3274
3284
} else if (LockingMode == LM_LEGACY) {
3275
- // Check if it is still a light weight lock, this is true if we see
3285
+ // Check if it is still a lightweight lock, this is true if we see
3276
3286
// the stack address of the basicLock in the markWord of the object
3277
3287
// copy box to currentHeader such that csg does not kill it.
3278
3288
z_lgr (currentHeader, box);
3279
- z_csg (currentHeader, displacedHeader, 0 , oop);
3289
+ z_csg (currentHeader, displacedHeader, hdr_offset , oop);
3280
3290
z_bru (done); // csg sets CR as desired.
3281
3291
} else {
3282
3292
assert (LockingMode == LM_LIGHTWEIGHT, " must be" );
3283
3293
3284
- // don't load currentHead again from stack-top after monitor check, as it is possible
3285
- // some other thread modified it.
3286
- // currentHeader is altered, but it's contents are copied in temp as well
3287
- lightweight_unlock (oop, temp, currentHeader, done);
3294
+ lightweight_unlock (oop, currentHeader, displacedHeader, done);
3288
3295
z_bru (done);
3289
3296
}
3290
3297
@@ -3293,11 +3300,22 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
3293
3300
3294
3301
// Handle existing monitor.
3295
3302
bind (object_has_monitor);
3296
- z_lg (currentHeader, hdr_offset, oop); // CurrentHeader is tagged with monitor_value set.
3297
- load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (recursions)));
3298
- z_brne (done);
3299
- load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (owner)));
3303
+
3304
+ z_cg (Z_thread, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (owner)));
3300
3305
z_brne (done);
3306
+
3307
+ BLOCK_COMMENT (" fast_path_recursive_unlock {" );
3308
+ load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (recursions)));
3309
+ z_bre (not_recursive); // if 0 then jump, it's not recursive locking
3310
+
3311
+ // Recursive inflated unlock
3312
+ z_agsi (Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (recursions)), -1ll );
3313
+ z_cgr (currentHeader, currentHeader); // set the CC to EQUAL
3314
+ BLOCK_COMMENT (" } fast_path_recursive_unlock" );
3315
+ z_bru (done);
3316
+
3317
+ bind (not_recursive);
3318
+
3301
3319
load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (EntryList)));
3302
3320
z_brne (done);
3303
3321
load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (cxq)));
0 commit comments