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