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