< prev index next >

src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp

Print this page

  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  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 "code/aotCodeCache.hpp"
  28 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  29 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  30 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  31 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  32 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  33 #include "gc/shenandoah/shenandoahHeapRegion.hpp"

  34 #include "gc/shenandoah/shenandoahRuntime.hpp"
  35 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  36 #include "interpreter/interpreter.hpp"

  37 #include "runtime/javaThread.hpp"
  38 #include "runtime/sharedRuntime.hpp"
  39 #include "utilities/macros.hpp"
  40 #ifdef COMPILER1
  41 #include "c1/c1_LIRAssembler.hpp"
  42 #include "c1/c1_MacroAssembler.hpp"
  43 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  44 #endif
  45 #ifdef COMPILER2
  46 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"

  47 #endif
  48 
  49 #define __ masm->
  50 
  51 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
  52                                                        Register src, Register dst, Register count) {
  53 
  54   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  55 
  56   if (is_reference_type(type)) {
  57     if (ShenandoahCardBarrier) {
  58       bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
  59       bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0;
  60       bool obj_int = (type == T_OBJECT) && UseCompressedOops;
  61 
  62       // We need to save the original element count because the array copy stub
  63       // will destroy the value and we need it for the card marking barrier.
  64       if (!checkcast) {
  65         if (!obj_int) {
  66           // Save count for barrier

 573   __ movptr(tmp, curr_ct_holder_addr);
 574 
 575   __ leaq(end, Address(addr, count, TIMES_OOP, 0));  // end == addr+count*oop_size
 576   __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
 577   __ shrptr(addr, CardTable::card_shift());
 578   __ shrptr(end, CardTable::card_shift());
 579   __ subptr(end, addr); // end --> cards count
 580 
 581   __ addptr(addr, tmp);
 582 
 583   __ BIND(L_loop);
 584   __ movb(Address(addr, count, Address::times_1), 0);
 585   __ decrement(count);
 586   __ jccb(Assembler::greaterEqual, L_loop);
 587 
 588   __ BIND(L_done);
 589 }
 590 
 591 #undef __
 592 













































 593 #ifdef COMPILER1
 594 
 595 #define __ ce->masm()->
 596 
 597 void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
 598   __ bind(*stub->entry());
 599 
 600   ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
 601 
 602   Register obj = stub->obj()->as_register();
 603 
 604   if (stub->do_load()) {
 605     ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, /* wide = */ false);
 606   }
 607   __ cmpptr(obj, NULL_WORD);
 608   __ jcc(Assembler::equal, *stub->continuation());
 609 
 610   ce->store_parameter(obj, 0);
 611   __ call(RuntimeAddress(bs->keepalive_barrier_stub()));
 612   __ jmp(*stub->continuation());

 761 
 762   __ lea(tmp1, addr);
 763   __ shrptr(tmp1, CardTable::card_shift());
 764   __ addptr(tmp1, Address(r15_thread, in_bytes(ShenandoahThreadLocalData::card_table_offset())));
 765   Address card_address(tmp1, 0);
 766 
 767   assert(CardTable::dirty_card_val() == 0, "Encoding assumption");
 768   Label L_done;
 769   if (UseCondCardMark) {
 770     __ cmpb(card_address, 0);
 771     __ jccb(Assembler::equal, L_done);
 772   }
 773   if (UseCompressedOops && CompressedOops::base() == nullptr) {
 774     __ movb(card_address, r12);
 775   } else {
 776     __ movb(card_address, 0);
 777   }
 778   __ bind(L_done);
 779 }
 780 
 781 void ShenandoahBarrierStubC2::enter_if_gc_state(MacroAssembler& masm, const char test_state, Register tmp) {
 782   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);



































 783 
 784   Address gc_state_fast(r15_thread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(test_state)));
 785   __ cmpb(gc_state_fast, 0);
 786   __ jcc(Assembler::notEqual, *entry());
 787   __ bind(*continuation());
 788 }
 789 

 790 void ShenandoahBarrierStubC2::emit_code(MacroAssembler& masm) {
 791   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 792   assert(_needs_keep_alive_barrier || _needs_load_ref_barrier, "Why are you here?");
 793 
 794   // On x86, there is a significant penalty with unaligned branch target, for example
 795   // when the target instruction straggles the fetch line. It makes (performance) sense
 796   // to spend some code size to align the target better.
 797   __ align(16);
 798   __ bind(*entry());
 799 
 800   // If we need to load ourselves, do it here.
 801   if (_do_load) {
 802     if (_narrow) {
 803       __ movl(_obj, _addr);
 804     } else {
 805       __ movq(_obj, _addr);
 806     }
 807   }
 808 
 809   // If the object is null, there is no point in applying barriers.

 814   bool needs_both_barriers = _needs_keep_alive_barrier && _needs_load_ref_barrier;
 815   if (!_do_load || needs_both_barriers) {
 816     preserve(_obj);
 817   }
 818 
 819   // Go for barriers. Barriers can return straight to continuation, as long
 820   // as another barrier is not needed.
 821   if (needs_both_barriers) {
 822     keepalive(masm, nullptr);
 823     lrb(masm);
 824   } else if (_needs_keep_alive_barrier) {
 825     keepalive(masm, continuation());
 826   } else if (_needs_load_ref_barrier) {
 827     lrb(masm);
 828   } else {
 829     ShouldNotReachHere();
 830   }
 831 }
 832 
 833 void ShenandoahBarrierStubC2::keepalive(MacroAssembler& masm, Label* L_done) {
 834   Address gc_state_fast(r15_thread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(ShenandoahHeap::MARKING)));
 835   Address index(r15_thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()));
 836   Address buffer(r15_thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()));
 837 
 838   Label L_through, L_pop_and_slow;
 839 
 840   // If another barrier is enabled as well, do a runtime check for a specific barrier.
 841   if (_needs_load_ref_barrier) {
 842     assert(L_done == nullptr, "L_done is always null when _needs_load_ref_barrier is true");
 843     __ cmpb(gc_state_fast, 0);
 844     __ jcc(Assembler::equal, L_through);
 845   }
 846 
 847   // Need temp to work, allocate one now.
 848   bool tmp_live;
 849   Register tmp = select_temp_register(tmp_live);
 850   if (tmp_live) {
 851     __ push(tmp);
 852   }
 853 
 854   // Fast-path: put object into buffer.
 855   // If buffer is already full, go slow.
 856   __ movptr(tmp, index);
 857   __ subptr(tmp, wordSize);
 858   // VerifyOops adds code for decoded oop and needs long jump here
 859   __ jcc(Assembler::below, L_pop_and_slow);
 860   __ movptr(index, tmp);
 861   __ addptr(tmp, buffer);
 862 
 863   // Store the object in queue.
 864   // If object is narrow, we need to decode it before inserting.

 894     // Shuffle in the arguments. The end result should be:
 895     //   c_rarg0 <-- obj
 896     if (c_rarg0 != _obj) {
 897       __ mov(c_rarg0, _obj);
 898     }
 899 
 900     // Go to runtime and handle the rest there.
 901     // Use rax as scratch, as it will be saved if live.
 902     __ call(RuntimeAddress(keepalive_runtime_entry_addr()), rax);
 903   }
 904   if (L_done != nullptr) {
 905     __ jmp(*L_done);
 906   } else {
 907     __ bind(L_through);
 908   }
 909 }
 910 
 911 void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) {
 912   Label L_pop_and_slow, L_slow;
 913 
 914   // If another barrier is enabled as well, do a runtime check for a specific barrier.
 915   if (_needs_keep_alive_barrier) {
 916     char state_to_check = ShenandoahHeap::HAS_FORWARDED | (_needs_load_ref_weak_barrier ? ShenandoahHeap::WEAK_ROOTS : 0);
 917     Address gc_state_fast(r15_thread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(state_to_check)));
 918     __ cmpb(gc_state_fast, 0);
 919     __ jcc(Assembler::equal, *continuation());
 920   }
 921 
 922   // If weak references are being processed, weak/phantom loads need to go slow,
 923   // regardless of their cset status.
 924   if (_needs_load_ref_weak_barrier) {
 925     Address gc_state_fast(r15_thread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(ShenandoahHeap::WEAK_ROOTS)));
 926     __ cmpb(gc_state_fast, 0);
 927     __ jccb(Assembler::notEqual, L_slow);
 928   }
 929 
 930   bool is_aot = AOTCodeCache::is_on_for_dump();
 931 
 932   // Need temp to work, allocate one now.
 933   bool tmp_live;
 934   Register tmp = select_temp_register(tmp_live, /* skip_reg1 = */ is_aot ? rcx : noreg);
 935   if (tmp_live) {
 936     __ push(tmp);
 937   }
 938 
 939   // Compute the cset bitmap index
 940   if (_narrow) {
 941     __ decode_heap_oop_not_null(tmp, _obj);
 942   } else {
 943     __ movptr(tmp, _obj);
 944   }
 945 
 946   Address cset_addr_arg;
 947   intptr_t cset_addr = reinterpret_cast<intptr_t>(ShenandoahHeap::in_cset_fast_test_addr());

  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  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 "code/aotCodeCache.hpp"
  28 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  29 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  30 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  31 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  32 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  33 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  34 #include "gc/shenandoah/shenandoahNMethod.inline.hpp"
  35 #include "gc/shenandoah/shenandoahRuntime.hpp"
  36 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  37 #include "interpreter/interpreter.hpp"
  38 #include "nativeInst_x86.hpp"
  39 #include "runtime/javaThread.hpp"
  40 #include "runtime/sharedRuntime.hpp"
  41 #include "utilities/macros.hpp"
  42 #ifdef COMPILER1
  43 #include "c1/c1_LIRAssembler.hpp"
  44 #include "c1/c1_MacroAssembler.hpp"
  45 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  46 #endif
  47 #ifdef COMPILER2
  48 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  49 #include "opto/output.hpp"
  50 #endif
  51 
  52 #define __ masm->
  53 
  54 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
  55                                                        Register src, Register dst, Register count) {
  56 
  57   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  58 
  59   if (is_reference_type(type)) {
  60     if (ShenandoahCardBarrier) {
  61       bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
  62       bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0;
  63       bool obj_int = (type == T_OBJECT) && UseCompressedOops;
  64 
  65       // We need to save the original element count because the array copy stub
  66       // will destroy the value and we need it for the card marking barrier.
  67       if (!checkcast) {
  68         if (!obj_int) {
  69           // Save count for barrier

 576   __ movptr(tmp, curr_ct_holder_addr);
 577 
 578   __ leaq(end, Address(addr, count, TIMES_OOP, 0));  // end == addr+count*oop_size
 579   __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
 580   __ shrptr(addr, CardTable::card_shift());
 581   __ shrptr(end, CardTable::card_shift());
 582   __ subptr(end, addr); // end --> cards count
 583 
 584   __ addptr(addr, tmp);
 585 
 586   __ BIND(L_loop);
 587   __ movb(Address(addr, count, Address::times_1), 0);
 588   __ decrement(count);
 589   __ jccb(Assembler::greaterEqual, L_loop);
 590 
 591   __ BIND(L_done);
 592 }
 593 
 594 #undef __
 595 
 596 address ShenandoahBarrierSetAssembler::parse_jump_address(address pc) {
 597   NativeInstruction* ni = nativeInstruction_at(pc);
 598   assert(ni->is_jump(), "Must be a jump");
 599   NativeJump* jmp = nativeJump_at(pc);
 600   return jmp->jump_destination();
 601 }
 602 
 603 void ShenandoahBarrierSetAssembler::insert_patchable_nop(address pc) {
 604   *(pc + 0) = 0x0F;
 605   *(pc + 1) = 0x1F;
 606   *(pc + 2) = 0x44;
 607   *(pc + 3) = 0x00;
 608   *(pc + 4) = 0x00;
 609 }
 610 
 611 bool ShenandoahBarrierSetAssembler::is_patchable_nop(address pc) {
 612   if (*(pc + 0) != 0x0F) return false;
 613   if (*(pc + 1) != 0x1F) return false;
 614   if (*(pc + 2) != 0x44) return false;
 615   if (*(pc + 3) != 0x00) return false;
 616   if (*(pc + 4) != 0x00) return false;
 617   return true;
 618 }
 619 
 620 void ShenandoahBarrierSetAssembler::insert_patchable_jump(address pc, address target_pc) {
 621   int32_t disp = checked_cast<int32_t>((intptr_t)target_pc - ((intptr_t)pc + 5));
 622 
 623   *(pc + 0) = 0xE9;
 624   *(pc + 1) = (disp >>  0) & 0xFF;
 625   *(pc + 2) = (disp >>  8) & 0xFF;
 626   *(pc + 3) = (disp >> 16) & 0xFF;
 627   *(pc + 4) = (disp >> 24) & 0xFF;
 628 }
 629 
 630 bool ShenandoahBarrierSetAssembler::is_patchable_jump(address pc, address target_pc) {
 631   int32_t disp = checked_cast<int32_t>((intptr_t)target_pc - ((intptr_t)pc + 5));
 632 
 633   if (*(pc + 0) != 0xE9) return false;
 634   if (*(pc + 1) != ((disp >>  0) & 0xFF)) return false;
 635   if (*(pc + 2) != ((disp >>  8) & 0xFF)) return false;
 636   if (*(pc + 3) != ((disp >> 16) & 0xFF)) return false;
 637   if (*(pc + 4) != ((disp >> 24) & 0xFF)) return false;
 638   return true;
 639 }
 640 
 641 #ifdef COMPILER1
 642 
 643 #define __ ce->masm()->
 644 
 645 void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
 646   __ bind(*stub->entry());
 647 
 648   ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
 649 
 650   Register obj = stub->obj()->as_register();
 651 
 652   if (stub->do_load()) {
 653     ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, /* wide = */ false);
 654   }
 655   __ cmpptr(obj, NULL_WORD);
 656   __ jcc(Assembler::equal, *stub->continuation());
 657 
 658   ce->store_parameter(obj, 0);
 659   __ call(RuntimeAddress(bs->keepalive_barrier_stub()));
 660   __ jmp(*stub->continuation());

 809 
 810   __ lea(tmp1, addr);
 811   __ shrptr(tmp1, CardTable::card_shift());
 812   __ addptr(tmp1, Address(r15_thread, in_bytes(ShenandoahThreadLocalData::card_table_offset())));
 813   Address card_address(tmp1, 0);
 814 
 815   assert(CardTable::dirty_card_val() == 0, "Encoding assumption");
 816   Label L_done;
 817   if (UseCondCardMark) {
 818     __ cmpb(card_address, 0);
 819     __ jccb(Assembler::equal, L_done);
 820   }
 821   if (UseCompressedOops && CompressedOops::base() == nullptr) {
 822     __ movb(card_address, r12);
 823   } else {
 824     __ movb(card_address, 0);
 825   }
 826   __ bind(L_done);
 827 }
 828 
 829 void ShenandoahBarrierStubC2::patchable_jump(MacroAssembler& masm, const char gc_state, bool jump_when_state, Register tmp1, Register tmp2, Label* L_target) {
 830 #ifdef ASSERT
 831   Label L_fake_entry, L_good;
 832   Address gc_state_addr(r15_thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
 833 
 834   // Emit the secondary jump and use it to cross-check against the actual GC state.
 835   // This also checks that all interesting GC state transitions are done non-racily
 836   // from the perspective of the thread executing the nmethod.
 837   __ relocate(patchable_barrier_Relocation::spec(ShenandoahNMethod::encode_to_reloc(gc_state, jump_when_state)));
 838   __ jmp(L_fake_entry, /* maybe_short = */ false);
 839 
 840   // Currently hot-patched to NOP.
 841   __ testb(gc_state_addr, gc_state);
 842   __ jccb(jump_when_state ? Assembler::zero : Assembler::notZero, L_good);
 843   __ hlt();
 844 
 845   // Currently hot-patched to JUMP.
 846   __ bind(L_fake_entry);
 847   __ testb(gc_state_addr, gc_state);
 848   __ jccb(jump_when_state ? Assembler::notZero : Assembler::zero, L_good);
 849   __ hlt();
 850 
 851   __ bind(L_good);
 852 #endif
 853 
 854   PhaseOutput* const output = Compile::current()->output();
 855   if (!output->in_scratch_emit_size()) {
 856     // Emit the unconditional branch in the first version of the method.
 857     // Let the rest of runtime figure out how to manage it.
 858     __ relocate(patchable_barrier_Relocation::spec(ShenandoahNMethod::encode_to_reloc(gc_state, jump_when_state)));
 859     __ jmp(*L_target, /* maybe_short = */ false);
 860   } else {
 861     // Avoid binding L_target in scratch emits.
 862     // We know the patchable check is exactly 5 bytes long.
 863     __ nop(5);
 864   }
 865 }
 866 
 867 void ShenandoahBarrierStubC2::enter_if_gc_state(MacroAssembler& masm, const char test_state, Register tmp1, Register tmp2) {
 868   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 869   patchable_jump_if_gc_state(masm, test_state, tmp1, tmp2, entry());
 870   __ bind(*continuation());
 871 }
 872 
 873 
 874 void ShenandoahBarrierStubC2::emit_code(MacroAssembler& masm) {
 875   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 876   assert(_needs_keep_alive_barrier || _needs_load_ref_barrier, "Why are you here?");
 877 
 878   // On x86, there is a significant penalty with unaligned branch target, for example
 879   // when the target instruction straggles the fetch line. It makes (performance) sense
 880   // to spend some code size to align the target better.
 881   __ align(16);
 882   __ bind(*entry());
 883 
 884   // If we need to load ourselves, do it here.
 885   if (_do_load) {
 886     if (_narrow) {
 887       __ movl(_obj, _addr);
 888     } else {
 889       __ movq(_obj, _addr);
 890     }
 891   }
 892 
 893   // If the object is null, there is no point in applying barriers.

 898   bool needs_both_barriers = _needs_keep_alive_barrier && _needs_load_ref_barrier;
 899   if (!_do_load || needs_both_barriers) {
 900     preserve(_obj);
 901   }
 902 
 903   // Go for barriers. Barriers can return straight to continuation, as long
 904   // as another barrier is not needed.
 905   if (needs_both_barriers) {
 906     keepalive(masm, nullptr);
 907     lrb(masm);
 908   } else if (_needs_keep_alive_barrier) {
 909     keepalive(masm, continuation());
 910   } else if (_needs_load_ref_barrier) {
 911     lrb(masm);
 912   } else {
 913     ShouldNotReachHere();
 914   }
 915 }
 916 
 917 void ShenandoahBarrierStubC2::keepalive(MacroAssembler& masm, Label* L_done) {

 918   Address index(r15_thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()));
 919   Address buffer(r15_thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()));
 920 
 921   Label L_through, L_pop_and_slow;
 922 
 923   // If another barrier is enabled as well, do a check for a specific barrier.
 924   if (_needs_load_ref_barrier) {
 925     assert(L_done == nullptr, "Should be");
 926     char state_to_check = ShenandoahHeap::MARKING;
 927     patchable_jump_if_not_gc_state(masm, state_to_check, noreg, noreg, &L_through);
 928   }
 929 
 930   // Need temp to work, allocate one now.
 931   bool tmp_live;
 932   Register tmp = select_temp_register(tmp_live);
 933   if (tmp_live) {
 934     __ push(tmp);
 935   }
 936 
 937   // Fast-path: put object into buffer.
 938   // If buffer is already full, go slow.
 939   __ movptr(tmp, index);
 940   __ subptr(tmp, wordSize);
 941   // VerifyOops adds code for decoded oop and needs long jump here
 942   __ jcc(Assembler::below, L_pop_and_slow);
 943   __ movptr(index, tmp);
 944   __ addptr(tmp, buffer);
 945 
 946   // Store the object in queue.
 947   // If object is narrow, we need to decode it before inserting.

 977     // Shuffle in the arguments. The end result should be:
 978     //   c_rarg0 <-- obj
 979     if (c_rarg0 != _obj) {
 980       __ mov(c_rarg0, _obj);
 981     }
 982 
 983     // Go to runtime and handle the rest there.
 984     // Use rax as scratch, as it will be saved if live.
 985     __ call(RuntimeAddress(keepalive_runtime_entry_addr()), rax);
 986   }
 987   if (L_done != nullptr) {
 988     __ jmp(*L_done);
 989   } else {
 990     __ bind(L_through);
 991   }
 992 }
 993 
 994 void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) {
 995   Label L_pop_and_slow, L_slow;
 996 
 997   // If another barrier is enabled as well, do a check for a specific barrier.
 998   if (_needs_keep_alive_barrier) {
 999     char state_to_check = ShenandoahHeap::HAS_FORWARDED | (_needs_load_ref_weak_barrier ? ShenandoahHeap::WEAK_ROOTS : 0);
1000     patchable_jump_if_not_gc_state(masm, state_to_check, noreg, noreg, continuation());


1001   }
1002 
1003   // If weak references are being processed, weak/phantom loads need to go slow,
1004   // regardless of their cset status.
1005   if (_needs_load_ref_weak_barrier) {
1006     char state_to_check = ShenandoahHeap::WEAK_ROOTS;
1007     patchable_jump_if_gc_state(masm, state_to_check, noreg, noreg, &L_slow);

1008   }
1009 
1010   bool is_aot = AOTCodeCache::is_on_for_dump();
1011 
1012   // Need temp to work, allocate one now.
1013   bool tmp_live;
1014   Register tmp = select_temp_register(tmp_live, /* skip_reg1 = */ is_aot ? rcx : noreg);
1015   if (tmp_live) {
1016     __ push(tmp);
1017   }
1018 
1019   // Compute the cset bitmap index
1020   if (_narrow) {
1021     __ decode_heap_oop_not_null(tmp, _obj);
1022   } else {
1023     __ movptr(tmp, _obj);
1024   }
1025 
1026   Address cset_addr_arg;
1027   intptr_t cset_addr = reinterpret_cast<intptr_t>(ShenandoahHeap::in_cset_fast_test_addr());
< prev index next >