1 /* 2 * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. 3 * Copyright (c) 2012, 2021 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "gc/shared/gcArguments.hpp" 27 #include "gc/shared/gc_globals.hpp" 28 #include "macroAssembler_ppc.hpp" 29 #include "precompiled.hpp" 30 #include "asm/macroAssembler.inline.hpp" 31 #include "gc/shenandoah/shenandoahBarrierSet.hpp" 32 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" 33 #include "gc/shenandoah/shenandoahForwarding.hpp" 34 #include "gc/shenandoah/shenandoahHeap.hpp" 35 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 36 #include "gc/shenandoah/shenandoahHeapRegion.hpp" 37 #include "gc/shenandoah/shenandoahRuntime.hpp" 38 #include "gc/shenandoah/shenandoahThreadLocalData.hpp" 39 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" 40 #include "interpreter/interpreter.hpp" 41 #include "runtime/javaThread.hpp" 42 #include "runtime/sharedRuntime.hpp" 43 #include "utilities/globalDefinitions.hpp" 44 #include "vm_version_ppc.hpp" 45 #ifdef COMPILER1 46 #include "c1/c1_LIRAssembler.hpp" 47 #include "c1/c1_MacroAssembler.hpp" 48 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" 49 #endif 50 51 #define __ masm-> 52 53 void ShenandoahBarrierSetAssembler::satb_write_barrier(MacroAssembler *masm, 54 Register base, RegisterOrConstant ind_or_offs, 55 Register tmp1, Register tmp2, Register tmp3, 56 MacroAssembler::PreservationLevel preservation_level) { 57 if (ShenandoahSATBBarrier) { 58 __ block_comment("satb_write_barrier (shenandoahgc) {"); 59 satb_write_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level); 60 __ block_comment("} satb_write_barrier (shenandoahgc)"); 61 } 62 } 63 64 void ShenandoahBarrierSetAssembler::iu_barrier(MacroAssembler *masm, 65 Register val, 66 Register tmp1, Register tmp2, 67 MacroAssembler::PreservationLevel preservation_level, 68 DecoratorSet decorators) { 69 // IU barriers are also employed to avoid resurrection of weak references, 70 // even if Shenandoah does not operate in incremental update mode. 71 if (ShenandoahIUBarrier || ShenandoahSATBBarrier) { 72 __ block_comment("iu_barrier (shenandoahgc) {"); 73 satb_write_barrier_impl(masm, decorators, noreg, noreg, val, tmp1, tmp2, preservation_level); 74 __ block_comment("} iu_barrier (shenandoahgc)"); 75 } 76 } 77 78 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators, 79 Register base, RegisterOrConstant ind_or_offs, 80 Register dst, 81 Register tmp1, Register tmp2, 82 MacroAssembler::PreservationLevel preservation_level) { 83 if (ShenandoahLoadRefBarrier) { 84 __ block_comment("load_reference_barrier (shenandoahgc) {"); 85 load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level); 86 __ block_comment("} load_reference_barrier (shenandoahgc)"); 87 } 88 } 89 90 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type, 91 Register src, Register dst, Register count, 92 Register preserve1, Register preserve2) { 93 __ block_comment("arraycopy_prologue (shenandoahgc) {"); 94 95 Register R11_tmp = R11_scratch1; 96 97 assert_different_registers(src, dst, count, R11_tmp, noreg); 98 if (preserve1 != noreg) { 99 // Technically not required, but likely to indicate an error. 100 assert_different_registers(preserve1, preserve2); 101 } 102 103 /* ==== Check whether barrier is required (optimizations) ==== */ 104 // Fast path: Component type of array is not a reference type. 105 if (!is_reference_type(type)) { 106 return; 107 } 108 109 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; 110 111 // Fast path: No barrier required if for every barrier type, it is either disabled or would not store 112 // any useful information. 113 if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahIUBarrier && !ShenandoahLoadRefBarrier) { 114 return; 115 } 116 117 Label skip_prologue; 118 119 // Fast path: Array is of length zero. 120 __ cmpdi(CCR0, count, 0); 121 __ beq(CCR0, skip_prologue); 122 123 /* ==== Check whether barrier is required (gc state) ==== */ 124 __ lbz(R11_tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), 125 R16_thread); 126 127 // The set of garbage collection states requiring barriers depends on the available barrier types and the 128 // type of the reference in question. 129 // For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant 130 // for the garbage collector. 131 const int required_states = ShenandoahSATBBarrier && dest_uninitialized 132 ? ShenandoahHeap::HAS_FORWARDED 133 : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING; 134 135 __ andi_(R11_tmp, R11_tmp, required_states); 136 __ beq(CCR0, skip_prologue); 137 138 /* ==== Invoke runtime ==== */ 139 // Save to-be-preserved registers. 140 int highest_preserve_register_index = 0; 141 { 142 if (preserve1 != noreg && preserve1->is_volatile()) { 143 __ std(preserve1, -BytesPerWord * ++highest_preserve_register_index, R1_SP); 144 } 145 if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) { 146 __ std(preserve2, -BytesPerWord * ++highest_preserve_register_index, R1_SP); 147 } 148 149 __ std(src, -BytesPerWord * ++highest_preserve_register_index, R1_SP); 150 __ std(dst, -BytesPerWord * ++highest_preserve_register_index, R1_SP); 151 __ std(count, -BytesPerWord * ++highest_preserve_register_index, R1_SP); 152 153 __ save_LR_CR(R11_tmp); 154 __ push_frame_reg_args(-BytesPerWord * highest_preserve_register_index, 155 R11_tmp); 156 } 157 158 // Invoke runtime. 159 address jrt_address = nullptr; 160 if (UseCompressedOops) { 161 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry); 162 } else { 163 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry); 164 } 165 assert(jrt_address != nullptr, "jrt routine cannot be found"); 166 167 __ call_VM_leaf(jrt_address, src, dst, count); 168 169 // Restore to-be-preserved registers. 170 { 171 __ pop_frame(); 172 __ restore_LR_CR(R11_tmp); 173 174 __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP); 175 __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP); 176 __ ld(src, -BytesPerWord * highest_preserve_register_index--, R1_SP); 177 178 if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) { 179 __ ld(preserve2, -BytesPerWord * highest_preserve_register_index--, R1_SP); 180 } 181 if (preserve1 != noreg && preserve1->is_volatile()) { 182 __ ld(preserve1, -BytesPerWord * highest_preserve_register_index--, R1_SP); 183 } 184 } 185 186 __ bind(skip_prologue); 187 __ block_comment("} arraycopy_prologue (shenandoahgc)"); 188 } 189 190 // The to-be-enqueued value can either be determined 191 // - dynamically by passing the reference's address information (load mode) or 192 // - statically by passing a register the value is stored in (preloaded mode) 193 // - for performance optimizations in cases where the previous value is known (currently not implemented) and 194 // - for incremental-update barriers. 195 // 196 // decorators: The previous value's decorator set. 197 // In "load mode", the value must equal '0'. 198 // base: Base register of the reference's address (load mode). 199 // In "preloaded mode", the register must equal 'noreg'. 200 // ind_or_offs: Index or offset of the reference's address (load mode). 201 // If 'base' equals 'noreg' (preloaded mode), the passed value is ignored. 202 // pre_val: Register holding the to-be-stored value (preloaded mode). 203 // In "load mode", this register acts as a temporary register and must 204 // thus not be 'noreg'. In "preloaded mode", its content will be sustained. 205 // tmp1/tmp2: Temporary registers, one of which must be non-volatile in "preloaded mode". 206 void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm, DecoratorSet decorators, 207 Register base, RegisterOrConstant ind_or_offs, 208 Register pre_val, 209 Register tmp1, Register tmp2, 210 MacroAssembler::PreservationLevel preservation_level) { 211 assert_different_registers(tmp1, tmp2, pre_val, noreg); 212 213 Label skip_barrier; 214 215 /* ==== Determine necessary runtime invocation preservation measures ==== */ 216 const bool needs_frame = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR; 217 const bool preserve_gp_registers = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR_GP_REGS; 218 const bool preserve_fp_registers = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS; 219 220 // Check whether marking is active. 221 __ lbz(tmp1, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread); 222 223 __ andi_(tmp1, tmp1, ShenandoahHeap::MARKING); 224 __ beq(CCR0, skip_barrier); 225 226 /* ==== Determine the reference's previous value ==== */ 227 bool preloaded_mode = base == noreg; 228 Register pre_val_save = noreg; 229 230 if (preloaded_mode) { 231 // Previous value has been passed to the method, so it must not be determined manually. 232 // In case 'pre_val' is a volatile register, it must be saved across the C-call 233 // as callers may depend on its value. 234 // Unless the general purposes registers are saved anyway, one of the temporary registers 235 // (i.e., 'tmp1' and 'tmp2') is used to the preserve 'pre_val'. 236 if (!preserve_gp_registers && pre_val->is_volatile()) { 237 pre_val_save = !tmp1->is_volatile() ? tmp1 : tmp2; 238 assert(!pre_val_save->is_volatile(), "at least one of the temporary registers must be non-volatile"); 239 } 240 241 if ((decorators & IS_NOT_NULL) != 0) { 242 #ifdef ASSERT 243 __ cmpdi(CCR0, pre_val, 0); 244 __ asm_assert_ne("null oop is not allowed"); 245 #endif // ASSERT 246 } else { 247 __ cmpdi(CCR0, pre_val, 0); 248 __ beq(CCR0, skip_barrier); 249 } 250 } else { 251 // Load from the reference address to determine the reference's current value (before the store is being performed). 252 // Contrary to the given value in "preloaded mode", it is not necessary to preserve it. 253 assert(decorators == 0, "decorator set must be empty"); 254 assert(base != noreg, "base must be a register"); 255 assert(!ind_or_offs.is_register() || ind_or_offs.as_register() != noreg, "ind_or_offs must be a register"); 256 if (UseCompressedOops) { 257 __ lwz(pre_val, ind_or_offs, base); 258 } else { 259 __ ld(pre_val, ind_or_offs, base); 260 } 261 262 __ cmpdi(CCR0, pre_val, 0); 263 __ beq(CCR0, skip_barrier); 264 265 if (UseCompressedOops) { 266 __ decode_heap_oop_not_null(pre_val); 267 } 268 } 269 270 /* ==== Try to enqueue the to-be-stored value directly into thread's local SATB mark queue ==== */ 271 { 272 Label runtime; 273 Register Rbuffer = tmp1, Rindex = tmp2; 274 275 // Check whether the queue has enough capacity to store another oop. 276 // If not, jump to the runtime to commit the buffer and to allocate a new one. 277 // (The buffer's index corresponds to the amount of remaining free space.) 278 __ ld(Rindex, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread); 279 __ cmpdi(CCR0, Rindex, 0); 280 __ beq(CCR0, runtime); // If index == 0 (buffer is full), goto runtime. 281 282 // Capacity suffices. Decrement the queue's size by the size of one oop. 283 // (The buffer is filled contrary to the heap's growing direction, i.e., it is filled downwards.) 284 __ addi(Rindex, Rindex, -wordSize); 285 __ std(Rindex, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread); 286 287 // Enqueue the previous value and skip the invocation of the runtime. 288 __ ld(Rbuffer, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()), R16_thread); 289 __ stdx(pre_val, Rbuffer, Rindex); 290 __ b(skip_barrier); 291 292 __ bind(runtime); 293 } 294 295 /* ==== Invoke runtime to commit SATB mark queue to gc and allocate a new buffer ==== */ 296 // Save to-be-preserved registers. 297 int nbytes_save = 0; 298 299 if (needs_frame) { 300 if (preserve_gp_registers) { 301 nbytes_save = (preserve_fp_registers 302 ? MacroAssembler::num_volatile_gp_regs + MacroAssembler::num_volatile_fp_regs 303 : MacroAssembler::num_volatile_gp_regs) * BytesPerWord; 304 __ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); 305 } 306 307 __ save_LR_CR(tmp1); 308 __ push_frame_reg_args(nbytes_save, tmp2); 309 } 310 311 if (!preserve_gp_registers && preloaded_mode && pre_val->is_volatile()) { 312 assert(pre_val_save != noreg, "nv_save must not be noreg"); 313 314 // 'pre_val' register must be saved manually unless general-purpose are preserved in general. 315 __ mr(pre_val_save, pre_val); 316 } 317 318 // Invoke runtime. 319 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, R16_thread); 320 321 // Restore to-be-preserved registers. 322 if (!preserve_gp_registers && preloaded_mode && pre_val->is_volatile()) { 323 __ mr(pre_val, pre_val_save); 324 } 325 326 if (needs_frame) { 327 __ pop_frame(); 328 __ restore_LR_CR(tmp1); 329 330 if (preserve_gp_registers) { 331 __ restore_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); 332 } 333 } 334 335 __ bind(skip_barrier); 336 } 337 338 void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssembler *masm, Register dst, Register tmp) { 339 __ block_comment("resolve_forward_pointer_not_null (shenandoahgc) {"); 340 341 Register tmp1 = tmp, 342 R0_tmp2 = R0; 343 assert_different_registers(dst, tmp1, R0_tmp2, noreg); 344 345 // If the object has been evacuated, the mark word layout is as follows: 346 // | forwarding pointer (62-bit) | '11' (2-bit) | 347 348 // The invariant that stack/thread pointers have the lowest two bits cleared permits retrieving 349 // the forwarding pointer solely by inversing the lowest two bits. 350 // This invariant follows inevitably from hotspot's minimal alignment. 351 assert(markWord::marked_value <= (unsigned long) MinObjAlignmentInBytes, 352 "marked value must not be higher than hotspot's minimal alignment"); 353 354 Label done; 355 356 // Load the object's mark word. 357 __ ld(tmp1, oopDesc::mark_offset_in_bytes(), dst); 358 359 // Load the bit mask for the lock bits. 360 __ li(R0_tmp2, markWord::lock_mask_in_place); 361 362 // Check whether all bits matching the bit mask are set. 363 // If that is the case, the object has been evacuated and the most significant bits form the forward pointer. 364 __ andc_(R0_tmp2, R0_tmp2, tmp1); 365 366 assert(markWord::lock_mask_in_place == markWord::marked_value, 367 "marked value must equal the value obtained when all lock bits are being set"); 368 if (VM_Version::has_isel()) { 369 __ xori(tmp1, tmp1, markWord::lock_mask_in_place); 370 __ isel(dst, CCR0, Assembler::equal, false, tmp1); 371 } else { 372 __ bne(CCR0, done); 373 __ xori(dst, tmp1, markWord::lock_mask_in_place); 374 } 375 376 __ bind(done); 377 __ block_comment("} resolve_forward_pointer_not_null (shenandoahgc)"); 378 } 379 380 // base: Base register of the reference's address. 381 // ind_or_offs: Index or offset of the reference's address (load mode). 382 // dst: Reference's address. In case the object has been evacuated, this is the to-space version 383 // of that object. 384 void ShenandoahBarrierSetAssembler::load_reference_barrier_impl( 385 MacroAssembler *masm, DecoratorSet decorators, 386 Register base, RegisterOrConstant ind_or_offs, 387 Register dst, 388 Register tmp1, Register tmp2, 389 MacroAssembler::PreservationLevel preservation_level) { 390 if (ind_or_offs.is_register()) { 391 assert_different_registers(tmp1, tmp2, base, ind_or_offs.as_register(), dst, noreg); 392 } else { 393 assert_different_registers(tmp1, tmp2, base, dst, noreg); 394 } 395 396 Label skip_barrier; 397 398 bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); 399 bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); 400 bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); 401 bool is_native = ShenandoahBarrierSet::is_native_access(decorators); 402 bool is_narrow = UseCompressedOops && !is_native; 403 404 /* ==== Check whether heap is stable ==== */ 405 __ lbz(tmp2, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread); 406 407 if (is_strong) { 408 // For strong references, the heap is considered stable if "has forwarded" is not active. 409 __ andi_(tmp1, tmp2, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION); 410 __ beq(CCR0, skip_barrier); 411 #ifdef ASSERT 412 // "evacuation" -> (implies) "has forwarded". If we reach this code, "has forwarded" must thus be set. 413 __ andi_(tmp1, tmp1, ShenandoahHeap::HAS_FORWARDED); 414 __ asm_assert_ne("'has forwarded' is missing"); 415 #endif // ASSERT 416 } else { 417 // For all non-strong references, the heap is considered stable if not any of "has forwarded", 418 // "root set processing", and "weak reference processing" is active. 419 // The additional phase conditions are in place to avoid the resurrection of weak references (see JDK-8266440). 420 Label skip_fastpath; 421 __ andi_(tmp1, tmp2, ShenandoahHeap::WEAK_ROOTS); 422 __ bne(CCR0, skip_fastpath); 423 424 __ andi_(tmp1, tmp2, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION); 425 __ beq(CCR0, skip_barrier); 426 #ifdef ASSERT 427 // "evacuation" -> (implies) "has forwarded". If we reach this code, "has forwarded" must thus be set. 428 __ andi_(tmp1, tmp1, ShenandoahHeap::HAS_FORWARDED); 429 __ asm_assert_ne("'has forwarded' is missing"); 430 #endif // ASSERT 431 432 __ bind(skip_fastpath); 433 } 434 435 /* ==== Check whether region is in collection set ==== */ 436 if (is_strong) { 437 // Shenandoah stores metadata on regions in a continuous area of memory in which a single byte corresponds to 438 // an entire region of the shenandoah heap. At present, only the least significant bit is of significance 439 // and indicates whether the region is part of the collection set. 440 // 441 // All regions are of the same size and are always aligned by a power of two. 442 // Any address can thus be shifted by a fixed number of bits to retrieve the address prefix shared by 443 // all objects within that region (region identification bits). 444 // 445 // | unused bits | region identification bits | object identification bits | 446 // (Region size depends on a couple of criteria, such as page size, user-provided arguments and the max heap size. 447 // The number of object identification bits can thus not be determined at compile time.) 448 // 449 // ------------------------------------------------------- <--- cs (collection set) base address 450 // | lost space due to heap space base address -> 'ShenandoahHeap::in_cset_fast_test_addr()' 451 // | (region identification bits contain heap base offset) 452 // |------------------------------------------------------ <--- cs base address + (heap_base >> region size shift) 453 // | collection set in the proper -> shift: 'region_size_bytes_shift_jint()' 454 // | 455 // |------------------------------------------------------ <--- cs base address + (heap_base >> region size shift) 456 // + number of regions 457 __ load_const_optimized(tmp2, ShenandoahHeap::in_cset_fast_test_addr(), tmp1); 458 __ srdi(tmp1, dst, ShenandoahHeapRegion::region_size_bytes_shift_jint()); 459 __ lbzx(tmp2, tmp1, tmp2); 460 __ andi_(tmp2, tmp2, 1); 461 __ beq(CCR0, skip_barrier); 462 } 463 464 /* ==== Invoke runtime ==== */ 465 // Save to-be-preserved registers. 466 int nbytes_save = 0; 467 468 const bool needs_frame = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR; 469 const bool preserve_gp_registers = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR_GP_REGS; 470 const bool preserve_fp_registers = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS; 471 472 if (needs_frame) { 473 if (preserve_gp_registers) { 474 nbytes_save = (preserve_fp_registers 475 ? MacroAssembler::num_volatile_gp_regs + MacroAssembler::num_volatile_fp_regs 476 : MacroAssembler::num_volatile_gp_regs) * BytesPerWord; 477 __ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); 478 } 479 480 __ save_LR_CR(tmp1); 481 __ push_frame_reg_args(nbytes_save, tmp1); 482 } 483 484 // Calculate the reference's absolute address. 485 __ add(R4_ARG2, ind_or_offs, base); 486 487 // Invoke runtime. 488 address jrt_address = nullptr; 489 490 if (is_strong) { 491 if (is_narrow) { 492 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow); 493 } else { 494 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong); 495 } 496 } else if (is_weak) { 497 if (is_narrow) { 498 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow); 499 } else { 500 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak); 501 } 502 } else { 503 assert(is_phantom, "only remaining strength"); 504 assert(!is_narrow, "phantom access cannot be narrow"); 505 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom); 506 } 507 assert(jrt_address != nullptr, "jrt routine cannot be found"); 508 509 __ call_VM_leaf(jrt_address, dst /* reference */, R4_ARG2 /* reference address */); 510 511 // Restore to-be-preserved registers. 512 if (preserve_gp_registers) { 513 __ mr(R0, R3_RET); 514 } else { 515 __ mr_if_needed(dst, R3_RET); 516 } 517 518 if (needs_frame) { 519 __ pop_frame(); 520 __ restore_LR_CR(tmp1); 521 522 if (preserve_gp_registers) { 523 __ restore_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); 524 __ mr(dst, R0); 525 } 526 } 527 528 __ bind(skip_barrier); 529 } 530 531 // base: Base register of the reference's address. 532 // ind_or_offs: Index or offset of the reference's address. 533 // L_handle_null: An optional label that will be jumped to if the reference is null. 534 void ShenandoahBarrierSetAssembler::load_at( 535 MacroAssembler *masm, DecoratorSet decorators, BasicType type, 536 Register base, RegisterOrConstant ind_or_offs, Register dst, 537 Register tmp1, Register tmp2, 538 MacroAssembler::PreservationLevel preservation_level, Label *L_handle_null) { 539 // Register must not clash, except 'base' and 'dst'. 540 if (ind_or_offs.is_register()) { 541 if (base != noreg) { 542 assert_different_registers(tmp1, tmp2, base, ind_or_offs.register_or_noreg(), R0, noreg); 543 } 544 assert_different_registers(tmp1, tmp2, dst, ind_or_offs.register_or_noreg(), R0, noreg); 545 } else { 546 if (base == noreg) { 547 assert_different_registers(tmp1, tmp2, base, R0, noreg); 548 } 549 assert_different_registers(tmp1, tmp2, dst, R0, noreg); 550 } 551 552 /* ==== Apply load barrier, if required ==== */ 553 if (ShenandoahBarrierSet::need_load_reference_barrier(decorators, type)) { 554 assert(is_reference_type(type), "need_load_reference_barrier must check whether type is a reference type"); 555 556 // If 'dst' clashes with either 'base' or 'ind_or_offs', use an intermediate result register 557 // to keep the values of those alive until the load reference barrier is applied. 558 Register intermediate_dst = (dst == base || (ind_or_offs.is_register() && dst == ind_or_offs.as_register())) 559 ? tmp2 560 : dst; 561 562 BarrierSetAssembler::load_at(masm, decorators, type, 563 base, ind_or_offs, 564 intermediate_dst, 565 tmp1, noreg, 566 preservation_level, L_handle_null); 567 568 load_reference_barrier(masm, decorators, 569 base, ind_or_offs, 570 intermediate_dst, 571 tmp1, R0, 572 preservation_level); 573 574 __ mr_if_needed(dst, intermediate_dst); 575 } else { 576 BarrierSetAssembler::load_at(masm, decorators, type, 577 base, ind_or_offs, 578 dst, 579 tmp1, tmp2, 580 preservation_level, L_handle_null); 581 } 582 583 /* ==== Apply keep-alive barrier, if required (e.g., to inhibit weak reference resurrection) ==== */ 584 if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) { 585 iu_barrier(masm, dst, tmp1, tmp2, preservation_level); 586 } 587 } 588 589 // base: Base register of the reference's address. 590 // ind_or_offs: Index or offset of the reference's address. 591 // val: To-be-stored value/reference's new value. 592 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type, 593 Register base, RegisterOrConstant ind_or_offs, Register val, 594 Register tmp1, Register tmp2, Register tmp3, 595 MacroAssembler::PreservationLevel preservation_level) { 596 if (is_reference_type(type)) { 597 if (ShenandoahSATBBarrier) { 598 satb_write_barrier(masm, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level); 599 } 600 601 if (ShenandoahIUBarrier && val != noreg) { 602 iu_barrier(masm, val, tmp1, tmp2, preservation_level, decorators); 603 } 604 } 605 606 BarrierSetAssembler::store_at(masm, decorators, type, 607 base, ind_or_offs, 608 val, 609 tmp1, tmp2, tmp3, 610 preservation_level); 611 } 612 613 void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm, 614 Register dst, Register jni_env, Register obj, 615 Register tmp, Label &slowpath) { 616 __ block_comment("try_resolve_jobject_in_native (shenandoahgc) {"); 617 618 assert_different_registers(jni_env, obj, tmp); 619 620 Label done; 621 622 // Fast path: Reference is null (JNI tags are zero for null pointers). 623 __ cmpdi(CCR0, obj, 0); 624 __ beq(CCR0, done); 625 626 // Resolve jobject using standard implementation. 627 BarrierSetAssembler::try_resolve_jobject_in_native(masm, dst, jni_env, obj, tmp, slowpath); 628 629 // Check whether heap is stable. 630 __ lbz(tmp, 631 in_bytes(ShenandoahThreadLocalData::gc_state_offset() - JavaThread::jni_environment_offset()), 632 jni_env); 633 634 __ andi_(tmp, tmp, ShenandoahHeap::EVACUATION | ShenandoahHeap::HAS_FORWARDED); 635 __ bne(CCR0, slowpath); 636 637 __ bind(done); 638 __ block_comment("} try_resolve_jobject_in_native (shenandoahgc)"); 639 } 640 641 // Special shenandoah CAS implementation that handles false negatives due 642 // to concurrent evacuation. That is, the CAS operation is intended to succeed in 643 // the following scenarios (success criteria): 644 // s1) The reference pointer ('base_addr') equals the expected ('expected') pointer. 645 // s2) The reference pointer refers to the from-space version of an already-evacuated 646 // object, whereas the expected pointer refers to the to-space version of the same object. 647 // Situations in which the reference pointer refers to the to-space version of an object 648 // and the expected pointer refers to the from-space version of the same object can not occur due to 649 // shenandoah's strong to-space invariant. This also implies that the reference stored in 'new_val' 650 // can not refer to the from-space version of an already-evacuated object. 651 // 652 // To guarantee correct behavior in concurrent environments, two races must be addressed: 653 // r1) A concurrent thread may heal the reference pointer (i.e., it is no longer referring to the 654 // from-space version but to the to-space version of the object in question). 655 // In this case, the CAS operation should succeed. 656 // r2) A concurrent thread may mutate the reference (i.e., the reference pointer refers to an entirely different object). 657 // In this case, the CAS operation should fail. 658 // 659 // By default, the value held in the 'result' register is zero to indicate failure of CAS, 660 // non-zero to indicate success. If 'is_cae' is set, the result is the most recently fetched 661 // value from 'base_addr' rather than a boolean success indicator. 662 void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler *masm, Register base_addr, 663 Register expected, Register new_val, Register tmp1, Register tmp2, 664 bool is_cae, Register result) { 665 __ block_comment("cmpxchg_oop (shenandoahgc) {"); 666 667 assert_different_registers(base_addr, new_val, tmp1, tmp2, result, R0); 668 assert_different_registers(base_addr, expected, tmp1, tmp2, result, R0); 669 670 // Potential clash of 'success_flag' and 'tmp' is being accounted for. 671 Register success_flag = is_cae ? noreg : result, 672 current_value = is_cae ? result : tmp1, 673 tmp = is_cae ? tmp1 : result, 674 initial_value = tmp2; 675 676 Label done, step_four; 677 678 __ bind(step_four); 679 680 /* ==== Step 1 ("Standard" CAS) ==== */ 681 // Fast path: The values stored in 'expected' and 'base_addr' are equal. 682 // Given that 'expected' must refer to the to-space object of an evacuated object (strong to-space invariant), 683 // no special processing is required. 684 if (UseCompressedOops) { 685 __ cmpxchgw(CCR0, current_value, expected, new_val, base_addr, MacroAssembler::MemBarNone, 686 false, success_flag, true); 687 } else { 688 __ cmpxchgd(CCR0, current_value, expected, new_val, base_addr, MacroAssembler::MemBarNone, 689 false, success_flag, nullptr, true); 690 } 691 692 // Skip the rest of the barrier if the CAS operation succeeds immediately. 693 // If it does not, the value stored at the address is either the from-space pointer of the 694 // referenced object (success criteria s2)) or simply another object. 695 __ beq(CCR0, done); 696 697 /* ==== Step 2 (Null check) ==== */ 698 // The success criteria s2) cannot be matched with a null pointer 699 // (null pointers cannot be subject to concurrent evacuation). The failure of the CAS operation is thus legitimate. 700 __ cmpdi(CCR0, current_value, 0); 701 __ beq(CCR0, done); 702 703 /* ==== Step 3 (reference pointer refers to from-space version; success criteria s2)) ==== */ 704 // To check whether the reference pointer refers to the from-space version, the forward 705 // pointer of the object referred to by the reference is resolved and compared against the expected pointer. 706 // If this check succeed, another CAS operation is issued with the from-space pointer being the expected pointer. 707 // 708 // Save the potential from-space pointer. 709 __ mr(initial_value, current_value); 710 711 // Resolve forward pointer. 712 if (UseCompressedOops) { __ decode_heap_oop_not_null(current_value); } 713 resolve_forward_pointer_not_null(masm, current_value, tmp); 714 if (UseCompressedOops) { __ encode_heap_oop_not_null(current_value); } 715 716 if (!is_cae) { 717 // 'success_flag' was overwritten by call to 'resovle_forward_pointer_not_null'. 718 // Load zero into register for the potential failure case. 719 __ li(success_flag, 0); 720 } 721 __ cmpd(CCR0, current_value, expected); 722 __ bne(CCR0, done); 723 724 // Discard fetched value as it might be a reference to the from-space version of an object. 725 if (UseCompressedOops) { 726 __ cmpxchgw(CCR0, R0, initial_value, new_val, base_addr, MacroAssembler::MemBarNone, 727 false, success_flag); 728 } else { 729 __ cmpxchgd(CCR0, R0, initial_value, new_val, base_addr, MacroAssembler::MemBarNone, 730 false, success_flag); 731 } 732 733 /* ==== Step 4 (Retry CAS with to-space pointer (success criteria s2) under race r1)) ==== */ 734 // The reference pointer could have been healed whilst the previous CAS operation was being performed. 735 // Another CAS operation must thus be issued with the to-space pointer being the expected pointer. 736 // If that CAS operation fails as well, race r2) must have occurred, indicating that 737 // the operation failure is legitimate. 738 // 739 // To keep the code's size small and thus improving cache (icache) performance, this highly 740 // unlikely case should be handled by the smallest possible code. Instead of emitting a third, 741 // explicit CAS operation, the code jumps back and reuses the first CAS operation (step 1) 742 // (passed arguments are identical). 743 // 744 // A failure of the CAS operation in step 1 would imply that the overall CAS operation is supposed 745 // to fail. Jumping back to step 1 requires, however, that step 2 and step 3 are re-executed as well. 746 // It is thus important to ensure that a re-execution of those steps does not put program correctness 747 // at risk: 748 // - Step 2: Either terminates in failure (desired result) or falls through to step 3. 749 // - Step 3: Terminates if the comparison between the forwarded, fetched pointer and the expected value 750 // fails. Unless the reference has been updated in the meanwhile once again, this is 751 // guaranteed to be the case. 752 // In case of a concurrent update, the CAS would be retried again. This is legitimate 753 // in terms of program correctness (even though it is not desired). 754 __ bne(CCR0, step_four); 755 756 __ bind(done); 757 __ block_comment("} cmpxchg_oop (shenandoahgc)"); 758 } 759 760 #undef __ 761 762 #ifdef COMPILER1 763 764 #define __ ce->masm()-> 765 766 void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) { 767 __ block_comment("gen_pre_barrier_stub (shenandoahgc) {"); 768 769 ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1(); 770 __ bind(*stub->entry()); 771 772 // GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'. 773 // This stub is the slowpath of that function. 774 775 assert(stub->pre_val()->is_register(), "pre_val must be a register"); 776 Register pre_val = stub->pre_val()->as_register(); 777 778 // If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()' 779 // ("preloaded mode" of the store barrier). 780 if (stub->do_load()) { 781 ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false); 782 } 783 784 // Fast path: Reference is null. 785 __ cmpdi(CCR0, pre_val, 0); 786 __ bc_far_optimized(Assembler::bcondCRbiIs1_bhintNoHint, __ bi0(CCR0, Assembler::equal), *stub->continuation()); 787 788 // Argument passing via the stack. 789 __ std(pre_val, -8, R1_SP); 790 791 __ load_const_optimized(R0, bs->pre_barrier_c1_runtime_code_blob()->code_begin()); 792 __ call_stub(R0); 793 794 __ b(*stub->continuation()); 795 __ block_comment("} gen_pre_barrier_stub (shenandoahgc)"); 796 } 797 798 void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler *ce, 799 ShenandoahLoadReferenceBarrierStub *stub) { 800 __ block_comment("gen_load_reference_barrier_stub (shenandoahgc) {"); 801 802 ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1(); 803 __ bind(*stub->entry()); 804 805 Register obj = stub->obj()->as_register(); 806 Register res = stub->result()->as_register(); 807 Register addr = stub->addr()->as_pointer_register(); 808 Register tmp1 = stub->tmp1()->as_register(); 809 Register tmp2 = stub->tmp2()->as_register(); 810 assert_different_registers(addr, res, tmp1, tmp2); 811 812 #ifdef ASSERT 813 // Ensure that 'res' is 'R3_ARG1' and contains the same value as 'obj' to reduce the number of required 814 // copy instructions. 815 assert(R3_RET == res, "res must be r3"); 816 __ cmpd(CCR0, res, obj); 817 __ asm_assert_eq("result register must contain the reference stored in obj"); 818 #endif 819 820 DecoratorSet decorators = stub->decorators(); 821 822 /* ==== Check whether region is in collection set ==== */ 823 // GC status (unstable) has already been verified by 'ShenandoahBarrierSetC1::load_reference_barrier_impl'. 824 // This stub is the slowpath of that function. 825 826 bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); 827 bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); 828 bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); 829 bool is_native = ShenandoahBarrierSet::is_native_access(decorators); 830 831 if (is_strong) { 832 // Check whether object is in collection set. 833 __ load_const_optimized(tmp2, ShenandoahHeap::in_cset_fast_test_addr(), tmp1); 834 __ srdi(tmp1, obj, ShenandoahHeapRegion::region_size_bytes_shift_jint()); 835 __ lbzx(tmp2, tmp1, tmp2); 836 837 __ andi_(tmp2, tmp2, 1); 838 __ bc_far_optimized(Assembler::bcondCRbiIs1_bhintNoHint, __ bi0(CCR0, Assembler::equal), *stub->continuation()); 839 } 840 841 address blob_addr = nullptr; 842 843 if (is_strong) { 844 if (is_native) { 845 blob_addr = bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin(); 846 } else { 847 blob_addr = bs->load_reference_barrier_strong_rt_code_blob()->code_begin(); 848 } 849 } else if (is_weak) { 850 blob_addr = bs->load_reference_barrier_weak_rt_code_blob()->code_begin(); 851 } else { 852 assert(is_phantom, "only remaining strength"); 853 blob_addr = bs->load_reference_barrier_phantom_rt_code_blob()->code_begin(); 854 } 855 856 assert(blob_addr != nullptr, "code blob cannot be found"); 857 858 // Argument passing via the stack. 'obj' is passed implicitly (as asserted above). 859 __ std(addr, -8, R1_SP); 860 861 __ load_const_optimized(tmp1, blob_addr, tmp2); 862 __ call_stub(tmp1); 863 864 // 'res' is 'R3_RET'. The result is thus already in the correct register. 865 866 __ b(*stub->continuation()); 867 __ block_comment("} gen_load_reference_barrier_stub (shenandoahgc)"); 868 } 869 870 #undef __ 871 872 #define __ sasm-> 873 874 void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler *sasm) { 875 __ block_comment("generate_c1_pre_barrier_runtime_stub (shenandoahgc) {"); 876 877 Label runtime, skip_barrier; 878 BarrierSet *bs = BarrierSet::barrier_set(); 879 880 // Argument passing via the stack. 881 const int caller_stack_slots = 3; 882 883 Register R0_pre_val = R0; 884 __ ld(R0, -8, R1_SP); 885 Register R11_tmp1 = R11_scratch1; 886 __ std(R11_tmp1, -16, R1_SP); 887 Register R12_tmp2 = R12_scratch2; 888 __ std(R12_tmp2, -24, R1_SP); 889 890 /* ==== Check whether marking is active ==== */ 891 // Even though gc status was checked in 'ShenandoahBarrierSetAssembler::gen_pre_barrier_stub', 892 // another check is required as a safepoint might have been reached in the meantime (JDK-8140588). 893 __ lbz(R12_tmp2, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread); 894 895 __ andi_(R12_tmp2, R12_tmp2, ShenandoahHeap::MARKING); 896 __ beq(CCR0, skip_barrier); 897 898 /* ==== Add previous value directly to thread-local SATB mark queue ==== */ 899 // Check queue's capacity. Jump to runtime if no free slot is available. 900 __ ld(R12_tmp2, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread); 901 __ cmpdi(CCR0, R12_tmp2, 0); 902 __ beq(CCR0, runtime); 903 904 // Capacity suffices. Decrement the queue's size by one slot (size of one oop). 905 __ addi(R12_tmp2, R12_tmp2, -wordSize); 906 __ std(R12_tmp2, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread); 907 908 // Enqueue the previous value and skip the runtime invocation. 909 __ ld(R11_tmp1, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()), R16_thread); 910 __ stdx(R0_pre_val, R11_tmp1, R12_tmp2); 911 __ b(skip_barrier); 912 913 __ bind(runtime); 914 915 /* ==== Invoke runtime to commit SATB mark queue to gc and allocate a new buffer ==== */ 916 // Save to-be-preserved registers. 917 const int nbytes_save = (MacroAssembler::num_volatile_regs + caller_stack_slots) * BytesPerWord; 918 __ save_volatile_gprs(R1_SP, -nbytes_save); 919 __ save_LR_CR(R11_tmp1); 920 __ push_frame_reg_args(nbytes_save, R11_tmp1); 921 922 // Invoke runtime. 923 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), R0_pre_val, R16_thread); 924 925 // Restore to-be-preserved registers. 926 __ pop_frame(); 927 __ restore_LR_CR(R11_tmp1); 928 __ restore_volatile_gprs(R1_SP, -nbytes_save); 929 930 __ bind(skip_barrier); 931 932 // Restore spilled registers. 933 __ ld(R11_tmp1, -16, R1_SP); 934 __ ld(R12_tmp2, -24, R1_SP); 935 936 __ blr(); 937 __ block_comment("} generate_c1_pre_barrier_runtime_stub (shenandoahgc)"); 938 } 939 940 void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler *sasm, 941 DecoratorSet decorators) { 942 __ block_comment("generate_c1_load_reference_barrier_runtime_stub (shenandoahgc) {"); 943 944 // Argument passing via the stack. 945 const int caller_stack_slots = 1; 946 947 // Save to-be-preserved registers. 948 const int nbytes_save = (MacroAssembler::num_volatile_regs - 1 // 'R3_ARG1' is skipped 949 + caller_stack_slots) * BytesPerWord; 950 __ save_volatile_gprs(R1_SP, -nbytes_save, true, false); 951 952 // Load arguments from stack. 953 // No load required, as assured by assertions in 'ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub'. 954 Register R3_obj = R3_ARG1; 955 Register R4_load_addr = R4_ARG2; 956 __ ld(R4_load_addr, -8, R1_SP); 957 958 Register R11_tmp = R11_scratch1; 959 960 /* ==== Invoke runtime ==== */ 961 bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); 962 bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); 963 bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); 964 bool is_native = ShenandoahBarrierSet::is_native_access(decorators); 965 966 address jrt_address = nullptr; 967 968 if (is_strong) { 969 if (is_native) { 970 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong); 971 } else { 972 if (UseCompressedOops) { 973 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow); 974 } else { 975 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong); 976 } 977 } 978 } else if (is_weak) { 979 assert(!is_native, "weak load reference barrier must not be called off-heap"); 980 if (UseCompressedOops) { 981 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow); 982 } else { 983 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak); 984 } 985 } else { 986 assert(is_phantom, "reference type must be phantom"); 987 assert(is_native, "phantom load reference barrier must be called off-heap"); 988 jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom); 989 } 990 assert(jrt_address != nullptr, "load reference barrier runtime routine cannot be found"); 991 992 __ save_LR_CR(R11_tmp); 993 __ push_frame_reg_args(nbytes_save, R11_tmp); 994 995 // Invoke runtime. Arguments are already stored in the corresponding registers. 996 __ call_VM_leaf(jrt_address, R3_obj, R4_load_addr); 997 998 // Restore to-be-preserved registers. 999 __ pop_frame(); 1000 __ restore_LR_CR(R11_tmp); 1001 __ restore_volatile_gprs(R1_SP, -nbytes_save, true, false); // Skip 'R3_RET' register. 1002 1003 __ blr(); 1004 __ block_comment("} generate_c1_load_reference_barrier_runtime_stub (shenandoahgc)"); 1005 } 1006 1007 #undef __ 1008 1009 #endif // COMPILER1