< 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/javaThread.hpp"
  44 #include "runtime/sharedRuntime.hpp"
  45 #include "utilities/globalDefinitions.hpp"
  46 #include "vm_version_ppc.hpp"
  47 #ifdef COMPILER1
  48 #include "c1/c1_LIRAssembler.hpp"
  49 #include "c1/c1_MacroAssembler.hpp"
  50 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  51 #endif
  52 #ifdef COMPILER2
  53 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  54 #include "opto/output.hpp"
  55 #endif
  56 
  57 #define __ masm->
  58 
  59 void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler *masm,
  60                                                  Register base, RegisterOrConstant ind_or_offs,
  61                                                  Register tmp1, Register tmp2, Register tmp3,
  62                                                  MacroAssembler::PreservationLevel preservation_level,
  63                                                  int extra_stack_space) {
  64   if (ShenandoahSATBBarrier) {
  65     __ block_comment("satb_barrier (shenandoahgc) {");
  66     satb_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level, extra_stack_space);
  67     __ block_comment("} satb_barrier (shenandoahgc)");
  68   }
  69 }
  70 
  71 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
  72                                                            Register base, RegisterOrConstant ind_or_offs,
  73                                                            Register dst,
  74                                                            Register tmp1, Register tmp2,

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

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


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

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

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

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

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

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

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