1
1
/*
2
2
* 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.
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
@@ -3196,28 +3196,32 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
3196
3196
Register temp = temp2;
3197
3197
NearLabel done, object_has_monitor;
3198
3198
3199
+ const int hdr_offset = oopDesc::mark_offset_in_bytes ();
3200
+
3201
+ assert_different_registers (temp1, temp2, oop, box);
3202
+
3199
3203
BLOCK_COMMENT (" compiler_fast_lock_object {" );
3200
3204
3201
3205
// Load markWord from oop into mark.
3202
- z_lg (displacedHeader, 0 , oop);
3206
+ z_lg (displacedHeader, hdr_offset , oop);
3203
3207
3204
3208
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 ()));
3207
3211
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 );
3209
3213
z_brne (done);
3210
3214
}
3211
3215
3212
3216
// Handle existing monitor.
3213
3217
// The object has an existing monitor iff (mark & monitor_value) != 0.
3214
3218
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);
3218
3221
3219
3222
if (LockingMode == LM_MONITOR) {
3220
3223
// Set NE to indicate 'failure' -> take slow-path
3224
+ // From loading the markWord, we know that oop != nullptr
3221
3225
z_ltgr (oop, oop);
3222
3226
z_bru (done);
3223
3227
} else if (LockingMode == LM_LEGACY) {
@@ -3229,23 +3233,24 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
3229
3233
// Initialize the box (must happen before we update the object mark).
3230
3234
z_stg (displacedHeader, BasicLock::displaced_header_offset_in_bytes (), box);
3231
3235
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);
3238
3239
assert (currentHeader == displacedHeader, " must be same register" ); // Identified two registers from z/Architecture.
3239
3240
z_bre (done);
3240
3241
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.
3243
3246
z_sgr (currentHeader, Z_SP);
3244
3247
load_const_optimized (temp, (~(os::vm_page_size () - 1 ) | markWord::lock_mask_in_place));
3245
3248
3246
3249
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
+
3249
3254
z_stg (currentHeader/* ==0 or not 0*/ , BasicLock::displaced_header_offset_in_bytes (), box);
3250
3255
3251
3256
z_bru (done);
@@ -3255,28 +3260,34 @@ void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Regis
3255
3260
z_bru (done);
3256
3261
}
3257
3262
3263
+ bind (object_has_monitor);
3264
+
3258
3265
Register zero = temp;
3259
3266
Register monitor_tagged = displacedHeader; // Tagged with markWord::monitor_value.
3260
- bind (object_has_monitor);
3261
3267
// The object's monitor m is unlocked iff m->owner is null,
3262
3268
// otherwise m->owner may contain a thread or a stack address.
3263
- //
3269
+
3264
3270
// Try to CAS m->owner from null to current thread.
3265
- z_lghi (zero, 0 );
3266
3271
// 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 );
3267
3274
z_csg (zero, Z_thread, OM_OFFSET_NO_MONITOR_VALUE_TAG (owner), monitor_tagged);
3268
3275
if (LockingMode != LM_LIGHTWEIGHT) {
3269
3276
// Store a non-null value into the box.
3270
3277
z_stg (box, BasicLock::displaced_header_offset_in_bytes (), box);
3271
3278
}
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" );
3280
3291
bind (done);
3281
3292
3282
3293
BLOCK_COMMENT (" } compiler_fast_lock_object" );
@@ -3289,11 +3300,12 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
3289
3300
Register displacedHeader = temp1;
3290
3301
Register currentHeader = temp2;
3291
3302
Register temp = temp1;
3292
- Register monitor = temp2;
3293
3303
3294
3304
const int hdr_offset = oopDesc::mark_offset_in_bytes ();
3295
3305
3296
- Label done, object_has_monitor;
3306
+ assert_different_registers (temp1, temp2, oop, box);
3307
+
3308
+ Label done, object_has_monitor, not_recursive;
3297
3309
3298
3310
BLOCK_COMMENT (" compiler_fast_unlock_object {" );
3299
3311
@@ -3308,30 +3320,25 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
3308
3320
// The object has an existing monitor iff (mark & monitor_value) != 0.
3309
3321
z_lg (currentHeader, hdr_offset, oop);
3310
3322
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);
3316
3326
3317
3327
if (LockingMode == LM_MONITOR) {
3318
3328
// Set NE to indicate 'failure' -> take slow-path
3319
3329
z_ltgr (oop, oop);
3320
3330
z_bru (done);
3321
3331
} 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
3323
3333
// the stack address of the basicLock in the markWord of the object
3324
3334
// copy box to currentHeader such that csg does not kill it.
3325
3335
z_lgr (currentHeader, box);
3326
- z_csg (currentHeader, displacedHeader, 0 , oop);
3336
+ z_csg (currentHeader, displacedHeader, hdr_offset , oop);
3327
3337
z_bru (done); // csg sets CR as desired.
3328
3338
} else {
3329
3339
assert (LockingMode == LM_LIGHTWEIGHT, " must be" );
3330
3340
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);
3335
3342
z_bru (done);
3336
3343
}
3337
3344
@@ -3340,11 +3347,22 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg
3340
3347
3341
3348
// Handle existing monitor.
3342
3349
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)));
3347
3352
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
+
3348
3366
load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (EntryList)));
3349
3367
z_brne (done);
3350
3368
load_and_test_long (temp, Address (currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG (cxq)));
0 commit comments