< prev index next >

src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp

Print this page

  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  *
  25  */
  26 
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "gc/shared/gc_globals.hpp"
  29 #include "gc/shared/gcArguments.hpp"
  30 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  31 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  32 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  33 #include "gc/shenandoah/shenandoahBarrierSetAssembler.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 "interpreter/interpreter.hpp"
  40 #include "macroAssembler_ppc.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 #ifdef COMPILER2
  51 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"

  52 #endif
  53 
  54 #define __ masm->
  55 
  56 void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler *masm,
  57                                                  Register base, RegisterOrConstant ind_or_offs,
  58                                                  Register tmp1, Register tmp2, Register tmp3,
  59                                                  MacroAssembler::PreservationLevel preservation_level,
  60                                                  int extra_stack_space) {
  61   if (ShenandoahSATBBarrier) {
  62     __ block_comment("satb_barrier (shenandoahgc) {");
  63     satb_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level, extra_stack_space);
  64     __ block_comment("} satb_barrier (shenandoahgc)");
  65   }
  66 }
  67 
  68 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
  69                                                            Register base, RegisterOrConstant ind_or_offs,
  70                                                            Register dst,
  71                                                            Register tmp1, Register tmp2,

 696   // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
 697   __ srdi(addr, addr, CardTable::card_shift());
 698   __ srdi(count, count, CardTable::card_shift());
 699   __ subf(count, addr, count);
 700   __ ld(R0, in_bytes(ShenandoahThreadLocalData::card_table_offset()), R16_thread);
 701   __ add(addr, addr, R0);
 702   __ addi(count, count, 1);
 703   __ li(R0, 0);
 704   __ mtctr(count);
 705 
 706   // Byte store loop
 707   __ bind(L_store_loop);
 708   __ stb(R0, 0, addr);
 709   __ addi(addr, addr, 1);
 710   __ bdnz(L_store_loop);
 711   __ bind(L_skip_loop);
 712 }
 713 
 714 #undef __
 715 
































 716 #ifdef COMPILER1
 717 
 718 #define __ ce->masm()->
 719 
 720 void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
 721   __ block_comment("keepalive_barrier_stub (shenandoahgc) {");
 722   __ bind(*stub->entry());
 723 
 724   ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
 725 
 726   Register obj = stub->obj()->as_register();
 727 
 728   // If 'do_load()' returns false, the to-be-stored value is already available in 'obj'
 729   if (stub->do_load()) {
 730     ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, false);
 731   }
 732 
 733   // Fast path: reference is null.
 734   __ cmpdi(CR0, obj, 0);
 735   __ bc_far_optimized(Assembler::bcondCRbiIs1_bhintNoHint, __ bi0(CR0, Assembler::equal), *stub->continuation());

 932 #define __ masm.
 933 
 934 void ShenandoahBarrierStubC2::cardtable(MacroAssembler& masm, Address address, Register tmp1, Register tmp2) {
 935   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 936   assert_different_registers(tmp1, tmp2, address.index(), address.base());
 937 
 938   __ ld(tmp1, in_bytes(ShenandoahThreadLocalData::card_table_offset()), R16_thread);
 939   if (address.index() == noreg) {
 940     __ add_const_optimized(tmp2, address.base(), address.disp(), R0);
 941   } else {
 942     __ add(tmp2, address.index(), address.base());
 943     if (address.disp() != 0) {
 944       __ addi(tmp2, tmp2, address.disp());
 945     }
 946   }
 947   __ srdi(tmp2, tmp2, CardTable::card_shift());
 948   __ li(R0, CardTable::dirty_card_val());
 949   __ stbx(R0, tmp2, tmp1);
 950 }
 951 
 952 void ShenandoahBarrierStubC2::enter_if_gc_state(MacroAssembler& masm, const char test_state, Register tmp) {
 953   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);












 954 
 955   __ lbz(tmp, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(test_state)), R16_thread);
 956   __ cmpdi(CR0, tmp, 0);
 957   // Branch to entry if not equal
 958   __ bc_far_optimized(Assembler::bcondCRbiIs0, __ bi0(CR0, Assembler::equal), *entry());
 959   // This is were the slowpath stub will return to
 960   __ bind(*continuation());
 961 }
 962 
 963 void ShenandoahBarrierStubC2::emit_code(MacroAssembler& masm) {
 964   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 965   assert(_needs_keep_alive_barrier || _needs_load_ref_barrier, "Why are you here?");
 966 
 967   __ bind(*entry());
 968 
 969   // If we need to load ourselves, do it here.
 970   if (_do_load) {
 971     if (_narrow) {
 972       __ lwz(_obj, _addr.disp(), _addr.base());
 973     } else {
 974       __ ld(_obj, _addr.disp(), _addr.base());
 975     }
 976   }
 977 
 978   // If the object is null, there is no point in applying barriers.
 979   maybe_far_jump_if_zero(masm, _obj);

 989   // as another barrier is not needed and we can reach the fastpath.
 990   if (needs_both_barriers) {
 991     keepalive(masm, nullptr);
 992     lrb(masm);
 993   } else if (_needs_keep_alive_barrier) {
 994     keepalive(masm, continuation());
 995   } else if (_needs_load_ref_barrier) {
 996     lrb(masm);
 997   } else {
 998     ShouldNotReachHere();
 999   }
1000 }
1001 
1002 void ShenandoahBarrierStubC2::maybe_far_jump_if_zero(MacroAssembler& masm, Register reg) {
1003   __ cmpdi(CR0, reg, 0);
1004   // Branch to continuation if equal
1005   __ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CR0, Assembler::equal), *continuation());
1006 }
1007 
1008 void ShenandoahBarrierStubC2::keepalive(MacroAssembler& masm, Label* L_done) {
1009   const int gcstate_offset = in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(ShenandoahHeap::MARKING));
1010   const int index_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset());
1011   const int buffer_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset());
1012   Label L_through, L_slowpath;
1013 
1014   // If another barrier is enabled as well, do a runtime check for a specific barrier.
1015   if (_needs_load_ref_barrier) {
1016     assert(L_done == nullptr, "L_done is always null when _needs_load_ref_barrier is true");
1017     __ lbz(_tmp1, gcstate_offset, R16_thread);
1018     __ cmpdi(CR0, _tmp1, 0);
1019     __ beq(CR0, L_through);
1020   }
1021 
1022   // Fast-path: put object into buffer.
1023   // If buffer is already full, go slow.
1024   __ ld(_tmp1, index_offset, R16_thread);
1025   __ cmpdi(CR0, _tmp1, 0);
1026   __ beq(CR0, L_slowpath);
1027   __ addi(_tmp1, _tmp1, -wordSize);
1028   __ std(_tmp1, index_offset, R16_thread);
1029   __ ld(_tmp2, buffer_offset, R16_thread);
1030 
1031   // Store the object in queue.
1032   // If object is narrow, we need to decode it before inserting.
1033   if (_narrow) {
1034     __ add(_tmp2, _tmp2, _tmp1);
1035     Register decoded = __ decode_heap_oop_not_null(_tmp1, _obj);
1036     __ stdx(decoded, _tmp2);
1037   } else {
1038     __ stdx(_obj, _tmp2, _tmp1);
1039   }

1048   // Slow-path: call runtime to handle.
1049   __ bind(L_slowpath);
1050 
1051   {
1052     SaveLiveRegisters slr(&masm, this);
1053 
1054     // Go to runtime and handle the rest there.
1055     __ call_VM_leaf(keepalive_runtime_entry_addr(), _obj);
1056   }
1057 
1058   if (L_done != nullptr) {
1059     __ b(*L_done);
1060   } else {
1061     __ bind(L_through);
1062   }
1063 }
1064 
1065 void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) {
1066   Label L_slow;
1067 
1068   // If another barrier is enabled as well, do a runtime check for a specific barrier.
1069   if (_needs_keep_alive_barrier) {
1070     char state_to_check = ShenandoahHeap::HAS_FORWARDED | (_needs_load_ref_weak_barrier ? ShenandoahHeap::WEAK_ROOTS : 0);
1071     __ lbz(_tmp1, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(state_to_check)), R16_thread);
1072     maybe_far_jump_if_zero(masm, _tmp1);
1073   }
1074 
1075   // If weak references are being processed, weak/phantom loads need to go slow,
1076   // regardless of their cset status.
1077   if (_needs_load_ref_weak_barrier) {
1078     __ lbz(_tmp1, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(ShenandoahHeap::WEAK_ROOTS)), R16_thread);
1079     __ cmpdi(CR0, _tmp1, 0);
1080     __ bne(CR0, L_slow);
1081   }
1082 
1083   // Cset-check. Fall-through to slow if in collection set.
1084   __ load_const_optimized(_tmp1, ShenandoahHeap::in_cset_fast_test_addr(), _tmp2);
1085   if (_narrow) {
1086     Register decoded = __ decode_heap_oop_not_null(_tmp2, _obj);
1087     __ srdi(_tmp2, decoded, ShenandoahHeapRegion::region_size_bytes_shift_jint());
1088   } else {
1089     __ srdi(_tmp2, _obj, ShenandoahHeapRegion::region_size_bytes_shift_jint());
1090   }
1091   __ lbzx(_tmp2, _tmp2, _tmp1);
1092   maybe_far_jump_if_zero(masm, _tmp2);
1093 
1094   // Slow path
1095   __ bind(L_slow);
1096 
1097   // Obj is the result, need to temporarily stop preserving it.
1098   bool is_obj_preserved = is_preserved(_obj);
1099   if (is_obj_preserved) {
1100     dont_preserve(_obj);

  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  *
  25  */
  26 
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "gc/shared/gc_globals.hpp"
  29 #include "gc/shared/gcArguments.hpp"
  30 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  31 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  32 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  33 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  34 #include "gc/shenandoah/shenandoahHeap.hpp"
  35 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  36 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  37 #include "gc/shenandoah/shenandoahNMethod.inline.hpp"
  38 #include "gc/shenandoah/shenandoahRuntime.hpp"
  39 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  40 #include "interpreter/interpreter.hpp"
  41 #include "macroAssembler_ppc.hpp"
  42 #include "nativeInst_ppc.hpp"
  43 #include "runtime/icache.hpp"
  44 #include "runtime/javaThread.hpp"
  45 #include "runtime/sharedRuntime.hpp"
  46 #include "utilities/globalDefinitions.hpp"
  47 #include "vm_version_ppc.hpp"
  48 #ifdef COMPILER1
  49 #include "c1/c1_LIRAssembler.hpp"
  50 #include "c1/c1_MacroAssembler.hpp"
  51 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  52 #endif
  53 #ifdef COMPILER2
  54 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  55 #include "opto/output.hpp"
  56 #endif
  57 
  58 #define __ masm->
  59 
  60 void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler *masm,
  61                                                  Register base, RegisterOrConstant ind_or_offs,
  62                                                  Register tmp1, Register tmp2, Register tmp3,
  63                                                  MacroAssembler::PreservationLevel preservation_level,
  64                                                  int extra_stack_space) {
  65   if (ShenandoahSATBBarrier) {
  66     __ block_comment("satb_barrier (shenandoahgc) {");
  67     satb_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level, extra_stack_space);
  68     __ block_comment("} satb_barrier (shenandoahgc)");
  69   }
  70 }
  71 
  72 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
  73                                                            Register base, RegisterOrConstant ind_or_offs,
  74                                                            Register dst,
  75                                                            Register tmp1, Register tmp2,

 700   // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
 701   __ srdi(addr, addr, CardTable::card_shift());
 702   __ srdi(count, count, CardTable::card_shift());
 703   __ subf(count, addr, count);
 704   __ ld(R0, in_bytes(ShenandoahThreadLocalData::card_table_offset()), R16_thread);
 705   __ add(addr, addr, R0);
 706   __ addi(count, count, 1);
 707   __ li(R0, 0);
 708   __ mtctr(count);
 709 
 710   // Byte store loop
 711   __ bind(L_store_loop);
 712   __ stb(R0, 0, addr);
 713   __ addi(addr, addr, 1);
 714   __ bdnz(L_store_loop);
 715   __ bind(L_skip_loop);
 716 }
 717 
 718 #undef __
 719 
 720 address ShenandoahBarrierSetAssembler::parse_jump_address(address pc) {
 721   NativeInstruction* ni = nativeInstruction_at(pc);
 722   assert(ni->is_jump(), "Must be");
 723   NativeGeneralJump* jmp = nativeGeneralJump_at(pc);
 724   return jmp->jump_destination();
 725 }
 726 
 727 static uint32_t encode_patchable_nop() {
 728   return 0x60000000;
 729 }
 730 
 731 void ShenandoahBarrierSetAssembler::insert_patchable_nop(address pc) {
 732   *((uint32_t*)pc) = encode_patchable_nop();
 733   ICache::invalidate_word(pc);
 734 }
 735 
 736 void ShenandoahBarrierSetAssembler::insert_patchable_jump(address pc, address target_pc) {
 737   CodeBuffer cb(pc, BytesPerInstWord + 1);
 738   MacroAssembler a(&cb);
 739   a.b(target_pc);
 740   ICache::invalidate_word(pc);
 741 }
 742 
 743 bool ShenandoahBarrierSetAssembler::is_patchable_nop(address pc) {
 744   return *((uint32_t*)pc) == encode_patchable_nop();
 745 }
 746 
 747 bool ShenandoahBarrierSetAssembler::is_patchable_jump(address pc, address target_pc) {
 748   NativeInstruction* ni = nativeInstruction_at(pc);
 749   return ni->is_jump() && nativeGeneralJump_at(pc)->jump_destination() == target_pc;
 750 }
 751 
 752 #ifdef COMPILER1
 753 
 754 #define __ ce->masm()->
 755 
 756 void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
 757   __ block_comment("keepalive_barrier_stub (shenandoahgc) {");
 758   __ bind(*stub->entry());
 759 
 760   ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
 761 
 762   Register obj = stub->obj()->as_register();
 763 
 764   // If 'do_load()' returns false, the to-be-stored value is already available in 'obj'
 765   if (stub->do_load()) {
 766     ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, false);
 767   }
 768 
 769   // Fast path: reference is null.
 770   __ cmpdi(CR0, obj, 0);
 771   __ bc_far_optimized(Assembler::bcondCRbiIs1_bhintNoHint, __ bi0(CR0, Assembler::equal), *stub->continuation());

 968 #define __ masm.
 969 
 970 void ShenandoahBarrierStubC2::cardtable(MacroAssembler& masm, Address address, Register tmp1, Register tmp2) {
 971   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 972   assert_different_registers(tmp1, tmp2, address.index(), address.base());
 973 
 974   __ ld(tmp1, in_bytes(ShenandoahThreadLocalData::card_table_offset()), R16_thread);
 975   if (address.index() == noreg) {
 976     __ add_const_optimized(tmp2, address.base(), address.disp(), R0);
 977   } else {
 978     __ add(tmp2, address.index(), address.base());
 979     if (address.disp() != 0) {
 980       __ addi(tmp2, tmp2, address.disp());
 981     }
 982   }
 983   __ srdi(tmp2, tmp2, CardTable::card_shift());
 984   __ li(R0, CardTable::dirty_card_val());
 985   __ stbx(R0, tmp2, tmp1);
 986 }
 987 
 988 void ShenandoahBarrierStubC2::patchable_jump(MacroAssembler& masm, const char gc_state, bool jump_when_state, Register tmp1, Register tmp2, Label* L_target) {
 989   PhaseOutput* const output = Compile::current()->output();
 990   if (output->in_scratch_emit_size()) {
 991     // Avoid binding L_target in scratch emits.
 992     // We know the patched check is exactly one instruction long.
 993     __ nop();
 994     return;
 995   }
 996 
 997   // Emit the unconditional branch in the first version of the method.
 998   // Let the rest of runtime figure out how to manage it.
 999   __ relocate(patchable_barrier_Relocation::spec(ShenandoahNMethod::encode_to_reloc(gc_state, jump_when_state)));
1000   __ b(*L_target);
1001 }
1002 
1003 void ShenandoahBarrierStubC2::enter_if_gc_state(MacroAssembler& masm, const char test_state, Register tmp1, Register tmp2) {
1004   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
1005   patchable_jump_if_gc_state(masm, test_state, tmp1, tmp2, entry());


1006   __ bind(*continuation());
1007 }
1008 
1009 void ShenandoahBarrierStubC2::emit_code(MacroAssembler& masm) {
1010   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
1011   assert(_needs_keep_alive_barrier || _needs_load_ref_barrier, "Why are you here?");
1012 
1013   __ bind(*entry());
1014 
1015   // If we need to load ourselves, do it here.
1016   if (_do_load) {
1017     if (_narrow) {
1018       __ lwz(_obj, _addr.disp(), _addr.base());
1019     } else {
1020       __ ld(_obj, _addr.disp(), _addr.base());
1021     }
1022   }
1023 
1024   // If the object is null, there is no point in applying barriers.
1025   maybe_far_jump_if_zero(masm, _obj);

1035   // as another barrier is not needed and we can reach the fastpath.
1036   if (needs_both_barriers) {
1037     keepalive(masm, nullptr);
1038     lrb(masm);
1039   } else if (_needs_keep_alive_barrier) {
1040     keepalive(masm, continuation());
1041   } else if (_needs_load_ref_barrier) {
1042     lrb(masm);
1043   } else {
1044     ShouldNotReachHere();
1045   }
1046 }
1047 
1048 void ShenandoahBarrierStubC2::maybe_far_jump_if_zero(MacroAssembler& masm, Register reg) {
1049   __ cmpdi(CR0, reg, 0);
1050   // Branch to continuation if equal
1051   __ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CR0, Assembler::equal), *continuation());
1052 }
1053 
1054 void ShenandoahBarrierStubC2::keepalive(MacroAssembler& masm, Label* L_done) {

1055   const int index_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset());
1056   const int buffer_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset());
1057   Label L_through, L_slowpath;
1058 
1059   // If another barrier is enabled as well, do a check for a specific barrier.
1060   if (_needs_load_ref_barrier) {
1061     assert(L_done == nullptr, "Should be");
1062     char state_to_check = ShenandoahHeap::MARKING;
1063     patchable_jump_if_not_gc_state(masm, state_to_check, _tmp1, _tmp2, &L_through);

1064   }
1065 
1066   // Fast-path: put object into buffer.
1067   // If buffer is already full, go slow.
1068   __ ld(_tmp1, index_offset, R16_thread);
1069   __ cmpdi(CR0, _tmp1, 0);
1070   __ beq(CR0, L_slowpath);
1071   __ addi(_tmp1, _tmp1, -wordSize);
1072   __ std(_tmp1, index_offset, R16_thread);
1073   __ ld(_tmp2, buffer_offset, R16_thread);
1074 
1075   // Store the object in queue.
1076   // If object is narrow, we need to decode it before inserting.
1077   if (_narrow) {
1078     __ add(_tmp2, _tmp2, _tmp1);
1079     Register decoded = __ decode_heap_oop_not_null(_tmp1, _obj);
1080     __ stdx(decoded, _tmp2);
1081   } else {
1082     __ stdx(_obj, _tmp2, _tmp1);
1083   }

1092   // Slow-path: call runtime to handle.
1093   __ bind(L_slowpath);
1094 
1095   {
1096     SaveLiveRegisters slr(&masm, this);
1097 
1098     // Go to runtime and handle the rest there.
1099     __ call_VM_leaf(keepalive_runtime_entry_addr(), _obj);
1100   }
1101 
1102   if (L_done != nullptr) {
1103     __ b(*L_done);
1104   } else {
1105     __ bind(L_through);
1106   }
1107 }
1108 
1109 void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) {
1110   Label L_slow;
1111 
1112   // If another barrier is enabled as well, do a check for a specific barrier.
1113   if (_needs_keep_alive_barrier) {
1114     char state_to_check = ShenandoahHeap::HAS_FORWARDED | (_needs_load_ref_weak_barrier ? ShenandoahHeap::WEAK_ROOTS : 0);
1115     patchable_jump_if_not_gc_state(masm, state_to_check, _tmp1, _tmp2, continuation());

1116   }
1117 
1118   // If weak references are being processed, weak/phantom loads need to go slow,
1119   // regardless of their cset status.
1120   if (_needs_load_ref_weak_barrier) {
1121     char state_to_check = ShenandoahHeap::WEAK_ROOTS;
1122     patchable_jump_if_gc_state(masm, state_to_check, _tmp1, _tmp2, &L_slow);

1123   }
1124 
1125   // Cset-check. Fall-through to slow if in collection set.
1126   __ load_const_optimized(_tmp1, ShenandoahHeap::in_cset_fast_test_addr(), _tmp2);
1127   if (_narrow) {
1128     Register decoded = __ decode_heap_oop_not_null(_tmp2, _obj);
1129     __ srdi(_tmp2, decoded, ShenandoahHeapRegion::region_size_bytes_shift_jint());
1130   } else {
1131     __ srdi(_tmp2, _obj, ShenandoahHeapRegion::region_size_bytes_shift_jint());
1132   }
1133   __ lbzx(_tmp2, _tmp2, _tmp1);
1134   maybe_far_jump_if_zero(masm, _tmp2);
1135 
1136   // Slow path
1137   __ bind(L_slow);
1138 
1139   // Obj is the result, need to temporarily stop preserving it.
1140   bool is_obj_preserved = is_preserved(_obj);
1141   if (is_obj_preserved) {
1142     dont_preserve(_obj);
< prev index next >