< prev index next >

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

Print this page

  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 "precompiled.hpp"
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "gc/shared/gcArguments.hpp"
  29 #include "gc/shared/gc_globals.hpp"
  30 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  31 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  32 #include "gc/shenandoah/shenandoahForwarding.hpp"
  33 #include "gc/shenandoah/shenandoahHeap.hpp"
  34 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  35 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  36 #include "gc/shenandoah/shenandoahRuntime.hpp"
  37 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  38 #include "gc/shenandoah/heuristics/shenandoahHeuristics.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 
  51 #define __ masm->
  52 
  53 void ShenandoahBarrierSetAssembler::satb_write_barrier(MacroAssembler *masm,
  54                                                        Register base, RegisterOrConstant ind_or_offs,
  55                                                        Register tmp1, Register tmp2, Register tmp3,
  56                                                        MacroAssembler::PreservationLevel preservation_level) {
  57   if (ShenandoahSATBBarrier) {
  58     __ block_comment("satb_write_barrier (shenandoahgc) {");
  59     satb_write_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
  60     __ block_comment("} satb_write_barrier (shenandoahgc)");
  61   }
  62 }
  63 
  64 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
  65                                                            Register base, RegisterOrConstant ind_or_offs,
  66                                                            Register dst,
  67                                                            Register tmp1, Register tmp2,
  68                                                            MacroAssembler::PreservationLevel preservation_level) {
  69   if (ShenandoahLoadRefBarrier) {
  70     __ block_comment("load_reference_barrier (shenandoahgc) {");
  71     load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level);
  72     __ block_comment("} load_reference_barrier (shenandoahgc)");
  73   }
  74 }
  75 
  76 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
  77                                                        Register src, Register dst, Register count,
  78                                                        Register preserve1, Register preserve2) {
  79   __ block_comment("arraycopy_prologue (shenandoahgc) {");
  80 
  81   Register R11_tmp = R11_scratch1;
  82 
  83   assert_different_registers(src, dst, count, R11_tmp, noreg);
  84   if (preserve1 != noreg) {
  85     // Technically not required, but likely to indicate an error.
  86     assert_different_registers(preserve1, preserve2);
  87   }
  88 
  89   /* ==== Check whether barrier is required (optimizations) ==== */
  90   // Fast path: Component type of array is not a reference type.
  91   if (!is_reference_type(type)) {
  92     return;
  93   }
  94 
  95   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  96 
  97   // Fast path: No barrier required if for every barrier type, it is either disabled or would not store
  98   // any useful information.
  99   if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahLoadRefBarrier) {
 100     return;
 101   }
 102 

 103   Label skip_prologue;
 104 
 105   // Fast path: Array is of length zero.
 106   __ cmpdi(CCR0, count, 0);
 107   __ beq(CCR0, skip_prologue);
 108 
 109   /* ==== Check whether barrier is required (gc state) ==== */
 110   __ lbz(R11_tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
 111          R16_thread);
 112 
 113   // The set of garbage collection states requiring barriers depends on the available barrier types and the
 114   // type of the reference in question.
 115   // For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant
 116   // for the garbage collector.
 117   const int required_states = ShenandoahSATBBarrier && dest_uninitialized
 118                               ? ShenandoahHeap::HAS_FORWARDED
 119                               : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING;
 120 
 121   __ andi_(R11_tmp, R11_tmp, required_states);
 122   __ beq(CCR0, skip_prologue);

 156   {
 157     __ pop_frame();
 158     __ restore_LR(R11_tmp);
 159 
 160     __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 161     __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 162     __ ld(src, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 163 
 164     if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) {
 165       __ ld(preserve2, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 166     }
 167     if (preserve1 != noreg && preserve1->is_volatile()) {
 168       __ ld(preserve1, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 169     }
 170   }
 171 
 172   __ bind(skip_prologue);
 173   __ block_comment("} arraycopy_prologue (shenandoahgc)");
 174 }
 175 










 176 // The to-be-enqueued value can either be determined
 177 // - dynamically by passing the reference's address information (load mode) or
 178 // - statically by passing a register the value is stored in (preloaded mode)
 179 //   - for performance optimizations in cases where the previous value is known (currently not implemented) and
 180 //   - for incremental-update barriers.
 181 //
 182 // decorators:  The previous value's decorator set.
 183 //              In "load mode", the value must equal '0'.
 184 // base:        Base register of the reference's address (load mode).
 185 //              In "preloaded mode", the register must equal 'noreg'.
 186 // ind_or_offs: Index or offset of the reference's address (load mode).
 187 //              If 'base' equals 'noreg' (preloaded mode), the passed value is ignored.
 188 // pre_val:     Register holding the to-be-stored value (preloaded mode).
 189 //              In "load mode", this register acts as a temporary register and must
 190 //              thus not be 'noreg'.  In "preloaded mode", its content will be sustained.
 191 // tmp1/tmp2:   Temporary registers, one of which must be non-volatile in "preloaded mode".
 192 void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm, DecoratorSet decorators,
 193                                                             Register base, RegisterOrConstant ind_or_offs,
 194                                                             Register pre_val,
 195                                                             Register tmp1, Register tmp2,

 559 
 560     __ mr_if_needed(dst, intermediate_dst);
 561   } else {
 562     BarrierSetAssembler::load_at(masm, decorators, type,
 563                                  base, ind_or_offs,
 564                                  dst,
 565                                  tmp1, tmp2,
 566                                  preservation_level, L_handle_null);
 567   }
 568 
 569   /* ==== Apply keep-alive barrier, if required (e.g., to inhibit weak reference resurrection) ==== */
 570   if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
 571     if (ShenandoahSATBBarrier) {
 572       __ block_comment("keep_alive_barrier (shenandoahgc) {");
 573       satb_write_barrier_impl(masm, 0, noreg, noreg, dst, tmp1, tmp2, preservation_level);
 574       __ block_comment("} keep_alive_barrier (shenandoahgc)");
 575     }
 576   }
 577 }
 578 



















 579 // base:        Base register of the reference's address.
 580 // ind_or_offs: Index or offset of the reference's address.
 581 // val:         To-be-stored value/reference's new value.
 582 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
 583                                              Register base, RegisterOrConstant ind_or_offs, Register val,
 584                                              Register tmp1, Register tmp2, Register tmp3,
 585                                              MacroAssembler::PreservationLevel preservation_level) {
 586   if (is_reference_type(type)) {
 587     if (ShenandoahSATBBarrier) {
 588       satb_write_barrier(masm, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
 589     }
 590   }
 591 
 592   BarrierSetAssembler::store_at(masm, decorators, type,
 593                                 base, ind_or_offs,
 594                                 val,
 595                                 tmp1, tmp2, tmp3,
 596                                 preservation_level);





 597 }
 598 
 599 void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
 600                                                                   Register dst, Register jni_env, Register obj,
 601                                                                   Register tmp, Label &slowpath) {
 602   __ block_comment("try_resolve_jobject_in_native (shenandoahgc) {");
 603 
 604   assert_different_registers(jni_env, obj, tmp);
 605 
 606   Label done;
 607 
 608   // Fast path: Reference is null (JNI tags are zero for null pointers).
 609   __ cmpdi(CCR0, obj, 0);
 610   __ beq(CCR0, done);
 611 
 612   // Resolve jobject using standard implementation.
 613   BarrierSetAssembler::try_resolve_jobject_in_native(masm, dst, jni_env, obj, tmp, slowpath);
 614 
 615   // Check whether heap is stable.
 616   __ lbz(tmp,

 726   // unlikely case should be handled by the smallest possible code.  Instead of emitting a third,
 727   // explicit CAS operation, the code jumps back and reuses the first CAS operation (step 1)
 728   // (passed arguments are identical).
 729   //
 730   // A failure of the CAS operation in step 1 would imply that the overall CAS operation is supposed
 731   // to fail.  Jumping back to step 1 requires, however, that step 2 and step 3 are re-executed as well.
 732   // It is thus important to ensure that a re-execution of those steps does not put program correctness
 733   // at risk:
 734   // - Step 2: Either terminates in failure (desired result) or falls through to step 3.
 735   // - Step 3: Terminates if the comparison between the forwarded, fetched pointer and the expected value
 736   //           fails.  Unless the reference has been updated in the meanwhile once again, this is
 737   //           guaranteed to be the case.
 738   //           In case of a concurrent update, the CAS would be retried again. This is legitimate
 739   //           in terms of program correctness (even though it is not desired).
 740   __ bne(CCR0, step_four);
 741 
 742   __ bind(done);
 743   __ block_comment("} cmpxchg_oop (shenandoahgc)");
 744 }
 745 


































 746 #undef __
 747 
 748 #ifdef COMPILER1
 749 
 750 #define __ ce->masm()->
 751 
 752 void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) {
 753   __ block_comment("gen_pre_barrier_stub (shenandoahgc) {");
 754 
 755   ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
 756   __ bind(*stub->entry());
 757 
 758   // GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'.
 759   // This stub is the slowpath of that function.
 760 
 761   assert(stub->pre_val()->is_register(), "pre_val must be a register");
 762   Register pre_val = stub->pre_val()->as_register();
 763 
 764   // If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()'
 765   // ("preloaded mode" of the store barrier).

  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 "precompiled.hpp"
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "gc/shared/gcArguments.hpp"
  29 #include "gc/shared/gc_globals.hpp"
  30 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  31 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  32 #include "gc/shenandoah/shenandoahForwarding.hpp"
  33 #include "gc/shenandoah/shenandoahHeap.hpp"
  34 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  35 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  36 #include "gc/shenandoah/shenandoahRuntime.hpp"
  37 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  38 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  39 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  40 #include "interpreter/interpreter.hpp"
  41 #include "macroAssembler_ppc.hpp"
  42 #include "runtime/javaThread.hpp"
  43 #include "runtime/sharedRuntime.hpp"
  44 #include "utilities/globalDefinitions.hpp"
  45 #include "vm_version_ppc.hpp"
  46 #ifdef COMPILER1
  47 #include "c1/c1_LIRAssembler.hpp"
  48 #include "c1/c1_MacroAssembler.hpp"
  49 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  50 #endif
  51 
  52 #define __ masm->
  53 
  54 void ShenandoahBarrierSetAssembler::satb_write_barrier(MacroAssembler *masm,
  55                                                        Register base, RegisterOrConstant ind_or_offs,
  56                                                        Register tmp1, Register tmp2, Register tmp3,
  57                                                        MacroAssembler::PreservationLevel preservation_level) {
  58   if (ShenandoahSATBBarrier) {
  59     __ block_comment("satb_write_barrier (shenandoahgc) {");
  60     satb_write_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
  61     __ block_comment("} satb_write_barrier (shenandoahgc)");
  62   }
  63 }
  64 
  65 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
  66                                                            Register base, RegisterOrConstant ind_or_offs,
  67                                                            Register dst,
  68                                                            Register tmp1, Register tmp2,
  69                                                            MacroAssembler::PreservationLevel preservation_level) {
  70   if (ShenandoahLoadRefBarrier) {
  71     __ block_comment("load_reference_barrier (shenandoahgc) {");
  72     load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level);
  73     __ block_comment("} load_reference_barrier (shenandoahgc)");
  74   }
  75 }
  76 
  77 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
  78                                                        Register src, Register dst, Register count,
  79                                                        Register preserve1, Register preserve2) {


  80   Register R11_tmp = R11_scratch1;
  81 
  82   assert_different_registers(src, dst, count, R11_tmp, noreg);
  83   if (preserve1 != noreg) {
  84     // Technically not required, but likely to indicate an error.
  85     assert_different_registers(preserve1, preserve2);
  86   }
  87 
  88   /* ==== Check whether barrier is required (optimizations) ==== */
  89   // Fast path: Component type of array is not a reference type.
  90   if (!is_reference_type(type)) {
  91     return;
  92   }
  93 
  94   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  95 
  96   // Fast path: No barrier required if for every barrier type, it is either disabled or would not store
  97   // any useful information.
  98   if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahLoadRefBarrier) {
  99     return;
 100   }
 101 
 102   __ block_comment("arraycopy_prologue (shenandoahgc) {");
 103   Label skip_prologue;
 104 
 105   // Fast path: Array is of length zero.
 106   __ cmpdi(CCR0, count, 0);
 107   __ beq(CCR0, skip_prologue);
 108 
 109   /* ==== Check whether barrier is required (gc state) ==== */
 110   __ lbz(R11_tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
 111          R16_thread);
 112 
 113   // The set of garbage collection states requiring barriers depends on the available barrier types and the
 114   // type of the reference in question.
 115   // For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant
 116   // for the garbage collector.
 117   const int required_states = ShenandoahSATBBarrier && dest_uninitialized
 118                               ? ShenandoahHeap::HAS_FORWARDED
 119                               : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING;
 120 
 121   __ andi_(R11_tmp, R11_tmp, required_states);
 122   __ beq(CCR0, skip_prologue);

 156   {
 157     __ pop_frame();
 158     __ restore_LR(R11_tmp);
 159 
 160     __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 161     __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 162     __ ld(src, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 163 
 164     if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) {
 165       __ ld(preserve2, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 166     }
 167     if (preserve1 != noreg && preserve1->is_volatile()) {
 168       __ ld(preserve1, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 169     }
 170   }
 171 
 172   __ bind(skip_prologue);
 173   __ block_comment("} arraycopy_prologue (shenandoahgc)");
 174 }
 175 
 176 void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
 177                                                        Register dst, Register count,
 178                                                        Register preserve) {
 179   if (ShenandoahCardBarrier && is_reference_type(type)) {
 180     __ block_comment("arraycopy_epilogue (shenandoahgc) {");
 181     gen_write_ref_array_post_barrier(masm, decorators, dst, count, preserve);
 182     __ block_comment("} arraycopy_epilogue (shenandoahgc)");
 183   }
 184 }
 185 
 186 // The to-be-enqueued value can either be determined
 187 // - dynamically by passing the reference's address information (load mode) or
 188 // - statically by passing a register the value is stored in (preloaded mode)
 189 //   - for performance optimizations in cases where the previous value is known (currently not implemented) and
 190 //   - for incremental-update barriers.
 191 //
 192 // decorators:  The previous value's decorator set.
 193 //              In "load mode", the value must equal '0'.
 194 // base:        Base register of the reference's address (load mode).
 195 //              In "preloaded mode", the register must equal 'noreg'.
 196 // ind_or_offs: Index or offset of the reference's address (load mode).
 197 //              If 'base' equals 'noreg' (preloaded mode), the passed value is ignored.
 198 // pre_val:     Register holding the to-be-stored value (preloaded mode).
 199 //              In "load mode", this register acts as a temporary register and must
 200 //              thus not be 'noreg'.  In "preloaded mode", its content will be sustained.
 201 // tmp1/tmp2:   Temporary registers, one of which must be non-volatile in "preloaded mode".
 202 void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm, DecoratorSet decorators,
 203                                                             Register base, RegisterOrConstant ind_or_offs,
 204                                                             Register pre_val,
 205                                                             Register tmp1, Register tmp2,

 569 
 570     __ mr_if_needed(dst, intermediate_dst);
 571   } else {
 572     BarrierSetAssembler::load_at(masm, decorators, type,
 573                                  base, ind_or_offs,
 574                                  dst,
 575                                  tmp1, tmp2,
 576                                  preservation_level, L_handle_null);
 577   }
 578 
 579   /* ==== Apply keep-alive barrier, if required (e.g., to inhibit weak reference resurrection) ==== */
 580   if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
 581     if (ShenandoahSATBBarrier) {
 582       __ block_comment("keep_alive_barrier (shenandoahgc) {");
 583       satb_write_barrier_impl(masm, 0, noreg, noreg, dst, tmp1, tmp2, preservation_level);
 584       __ block_comment("} keep_alive_barrier (shenandoahgc)");
 585     }
 586   }
 587 }
 588 
 589 void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register base, RegisterOrConstant ind_or_offs, Register tmp) {
 590   assert(ShenandoahCardBarrier, "Should have been checked by caller");
 591 
 592   ShenandoahBarrierSet* ctbs = ShenandoahBarrierSet::barrier_set();
 593   CardTable* ct = ctbs->card_table();
 594   assert_different_registers(base, tmp, R0);
 595 
 596   if (ind_or_offs.is_constant()) {
 597     __ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp);
 598   } else {
 599     __ add(base, ind_or_offs.as_register(), base);
 600   }
 601 
 602   __ load_const_optimized(tmp, (address)ct->byte_map_base(), R0);
 603   __ srdi(base, base, CardTable::card_shift());
 604   __ li(R0, CardTable::dirty_card_val());
 605   __ stbx(R0, tmp, base);
 606 }
 607 
 608 // base:        Base register of the reference's address.
 609 // ind_or_offs: Index or offset of the reference's address.
 610 // val:         To-be-stored value/reference's new value.
 611 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
 612                                              Register base, RegisterOrConstant ind_or_offs, Register val,
 613                                              Register tmp1, Register tmp2, Register tmp3,
 614                                              MacroAssembler::PreservationLevel preservation_level) {
 615   if (is_reference_type(type)) {
 616     if (ShenandoahSATBBarrier) {
 617       satb_write_barrier(masm, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
 618     }
 619   }
 620 
 621   BarrierSetAssembler::store_at(masm, decorators, type,
 622                                 base, ind_or_offs,
 623                                 val,
 624                                 tmp1, tmp2, tmp3,
 625                                 preservation_level);
 626 
 627   // No need for post barrier if storing NULL
 628   if (ShenandoahCardBarrier && is_reference_type(type) && val != noreg) {
 629     store_check(masm, base, ind_or_offs, tmp1);
 630   }
 631 }
 632 
 633 void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
 634                                                                   Register dst, Register jni_env, Register obj,
 635                                                                   Register tmp, Label &slowpath) {
 636   __ block_comment("try_resolve_jobject_in_native (shenandoahgc) {");
 637 
 638   assert_different_registers(jni_env, obj, tmp);
 639 
 640   Label done;
 641 
 642   // Fast path: Reference is null (JNI tags are zero for null pointers).
 643   __ cmpdi(CCR0, obj, 0);
 644   __ beq(CCR0, done);
 645 
 646   // Resolve jobject using standard implementation.
 647   BarrierSetAssembler::try_resolve_jobject_in_native(masm, dst, jni_env, obj, tmp, slowpath);
 648 
 649   // Check whether heap is stable.
 650   __ lbz(tmp,

 760   // unlikely case should be handled by the smallest possible code.  Instead of emitting a third,
 761   // explicit CAS operation, the code jumps back and reuses the first CAS operation (step 1)
 762   // (passed arguments are identical).
 763   //
 764   // A failure of the CAS operation in step 1 would imply that the overall CAS operation is supposed
 765   // to fail.  Jumping back to step 1 requires, however, that step 2 and step 3 are re-executed as well.
 766   // It is thus important to ensure that a re-execution of those steps does not put program correctness
 767   // at risk:
 768   // - Step 2: Either terminates in failure (desired result) or falls through to step 3.
 769   // - Step 3: Terminates if the comparison between the forwarded, fetched pointer and the expected value
 770   //           fails.  Unless the reference has been updated in the meanwhile once again, this is
 771   //           guaranteed to be the case.
 772   //           In case of a concurrent update, the CAS would be retried again. This is legitimate
 773   //           in terms of program correctness (even though it is not desired).
 774   __ bne(CCR0, step_four);
 775 
 776   __ bind(done);
 777   __ block_comment("} cmpxchg_oop (shenandoahgc)");
 778 }
 779 
 780 void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
 781                                                                      Register addr, Register count, Register preserve) {
 782   assert(ShenandoahCardBarrier, "Should have been checked by caller");
 783 
 784   ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
 785   CardTable* ct = bs->card_table();
 786   assert_different_registers(addr, count, R0);
 787 
 788   Label L_skip_loop, L_store_loop;
 789 
 790   __ sldi_(count, count, LogBytesPerHeapOop);
 791 
 792   // Zero length? Skip.
 793   __ beq(CCR0, L_skip_loop);
 794 
 795   __ addi(count, count, -BytesPerHeapOop);
 796   __ add(count, addr, count);
 797   // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
 798   __ srdi(addr, addr, CardTable::card_shift());
 799   __ srdi(count, count, CardTable::card_shift());
 800   __ subf(count, addr, count);
 801   __ add_const_optimized(addr, addr, (address)ct->byte_map_base(), R0);
 802   __ addi(count, count, 1);
 803   __ li(R0, 0);
 804   __ mtctr(count);
 805 
 806   // Byte store loop
 807   __ bind(L_store_loop);
 808   __ stb(R0, 0, addr);
 809   __ addi(addr, addr, 1);
 810   __ bdnz(L_store_loop);
 811   __ bind(L_skip_loop);
 812 }
 813 
 814 #undef __
 815 
 816 #ifdef COMPILER1
 817 
 818 #define __ ce->masm()->
 819 
 820 void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) {
 821   __ block_comment("gen_pre_barrier_stub (shenandoahgc) {");
 822 
 823   ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
 824   __ bind(*stub->entry());
 825 
 826   // GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'.
 827   // This stub is the slowpath of that function.
 828 
 829   assert(stub->pre_val()->is_register(), "pre_val must be a register");
 830   Register pre_val = stub->pre_val()->as_register();
 831 
 832   // If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()'
 833   // ("preloaded mode" of the store barrier).
< prev index next >