< prev index next >

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

Print this page

   1 /*
   2  * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
   3  * Copyright (c) 2012, 2021 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "gc/shared/gcArguments.hpp"
  27 #include "gc/shared/gc_globals.hpp"
  28 #include "macroAssembler_ppc.hpp"
  29 #include "precompiled.hpp"
  30 #include "asm/macroAssembler.inline.hpp"
  31 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  32 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  33 #include "gc/shenandoah/shenandoahForwarding.hpp"
  34 #include "gc/shenandoah/shenandoahHeap.hpp"
  35 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  36 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  37 #include "gc/shenandoah/shenandoahRuntime.hpp"
  38 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  39 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"

  40 #include "interpreter/interpreter.hpp"
  41 #include "runtime/javaThread.hpp"
  42 #include "runtime/sharedRuntime.hpp"
  43 #include "utilities/globalDefinitions.hpp"
  44 #include "vm_version_ppc.hpp"
  45 #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::iu_barrier(MacroAssembler *masm,
  65                                                Register val,
  66                                                Register tmp1, Register tmp2,
  67                                                MacroAssembler::PreservationLevel preservation_level,
  68                                                DecoratorSet decorators) {
  69   // IU barriers are also employed to avoid resurrection of weak references,
  70   // even if Shenandoah does not operate in incremental update mode.
  71   if (ShenandoahIUBarrier || ShenandoahSATBBarrier) {
  72     __ block_comment("iu_barrier (shenandoahgc) {");
  73     satb_write_barrier_impl(masm, decorators, noreg, noreg, val, tmp1, tmp2, preservation_level);
  74     __ block_comment("} iu_barrier (shenandoahgc)");
  75   }
  76 }
  77 
  78 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
  79                                                            Register base, RegisterOrConstant ind_or_offs,
  80                                                            Register dst,
  81                                                            Register tmp1, Register tmp2,
  82                                                            MacroAssembler::PreservationLevel preservation_level) {
  83   if (ShenandoahLoadRefBarrier) {
  84     __ block_comment("load_reference_barrier (shenandoahgc) {");
  85     load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level);
  86     __ block_comment("} load_reference_barrier (shenandoahgc)");
  87   }
  88 }
  89 
  90 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
  91                                                        Register src, Register dst, Register count,
  92                                                        Register preserve1, Register preserve2) {
  93   __ block_comment("arraycopy_prologue (shenandoahgc) {");
  94 
  95   Register R11_tmp = R11_scratch1;
  96 
  97   assert_different_registers(src, dst, count, R11_tmp, noreg);
  98   if (preserve1 != noreg) {
  99     // Technically not required, but likely to indicate an error.
 100     assert_different_registers(preserve1, preserve2);
 101   }
 102 
 103   /* ==== Check whether barrier is required (optimizations) ==== */
 104   // Fast path: Component type of array is not a reference type.
 105   if (!is_reference_type(type)) {
 106     return;
 107   }
 108 
 109   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
 110 
 111   // Fast path: No barrier required if for every barrier type, it is either disabled or would not store
 112   // any useful information.
 113   if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahIUBarrier && !ShenandoahLoadRefBarrier) {
 114     return;
 115   }
 116 

 117   Label skip_prologue;
 118 
 119   // Fast path: Array is of length zero.
 120   __ cmpdi(CCR0, count, 0);
 121   __ beq(CCR0, skip_prologue);
 122 
 123   /* ==== Check whether barrier is required (gc state) ==== */
 124   __ lbz(R11_tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
 125          R16_thread);
 126 
 127   // The set of garbage collection states requiring barriers depends on the available barrier types and the
 128   // type of the reference in question.
 129   // For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant
 130   // for the garbage collector.
 131   const int required_states = ShenandoahSATBBarrier && dest_uninitialized
 132                               ? ShenandoahHeap::HAS_FORWARDED
 133                               : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING;
 134 
 135   __ andi_(R11_tmp, R11_tmp, required_states);
 136   __ beq(CCR0, skip_prologue);

 170   {
 171     __ pop_frame();
 172     __ restore_LR_CR(R11_tmp);
 173 
 174     __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 175     __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 176     __ ld(src, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 177 
 178     if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) {
 179       __ ld(preserve2, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 180     }
 181     if (preserve1 != noreg && preserve1->is_volatile()) {
 182       __ ld(preserve1, -BytesPerWord * highest_preserve_register_index--, R1_SP);
 183     }
 184   }
 185 
 186   __ bind(skip_prologue);
 187   __ block_comment("} arraycopy_prologue (shenandoahgc)");
 188 }
 189 










 190 // The to-be-enqueued value can either be determined
 191 // - dynamically by passing the reference's address information (load mode) or
 192 // - statically by passing a register the value is stored in (preloaded mode)
 193 //   - for performance optimizations in cases where the previous value is known (currently not implemented) and
 194 //   - for incremental-update barriers.
 195 //
 196 // decorators:  The previous value's decorator set.
 197 //              In "load mode", the value must equal '0'.
 198 // base:        Base register of the reference's address (load mode).
 199 //              In "preloaded mode", the register must equal 'noreg'.
 200 // ind_or_offs: Index or offset of the reference's address (load mode).
 201 //              If 'base' equals 'noreg' (preloaded mode), the passed value is ignored.
 202 // pre_val:     Register holding the to-be-stored value (preloaded mode).
 203 //              In "load mode", this register acts as a temporary register and must
 204 //              thus not be 'noreg'.  In "preloaded mode", its content will be sustained.
 205 // tmp1/tmp2:   Temporary registers, one of which must be non-volatile in "preloaded mode".
 206 void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm, DecoratorSet decorators,
 207                                                             Register base, RegisterOrConstant ind_or_offs,
 208                                                             Register pre_val,
 209                                                             Register tmp1, Register tmp2,

 565                                  tmp1, noreg,
 566                                  preservation_level, L_handle_null);
 567 
 568     load_reference_barrier(masm, decorators,
 569                            base, ind_or_offs,
 570                            intermediate_dst,
 571                            tmp1, R0,
 572                            preservation_level);
 573 
 574     __ mr_if_needed(dst, intermediate_dst);
 575   } else {
 576     BarrierSetAssembler::load_at(masm, decorators, type,
 577                                  base, ind_or_offs,
 578                                  dst,
 579                                  tmp1, tmp2,
 580                                  preservation_level, L_handle_null);
 581   }
 582 
 583   /* ==== Apply keep-alive barrier, if required (e.g., to inhibit weak reference resurrection) ==== */
 584   if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
 585     iu_barrier(masm, dst, tmp1, tmp2, preservation_level);


















 586   }





 587 }
 588 
 589 // base:        Base register of the reference's address.
 590 // ind_or_offs: Index or offset of the reference's address.
 591 // val:         To-be-stored value/reference's new value.
 592 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
 593                                              Register base, RegisterOrConstant ind_or_offs, Register val,
 594                                              Register tmp1, Register tmp2, Register tmp3,
 595                                              MacroAssembler::PreservationLevel preservation_level) {
 596   if (is_reference_type(type)) {
 597     if (ShenandoahSATBBarrier) {
 598       satb_write_barrier(masm, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
 599     }
 600 
 601     if (ShenandoahIUBarrier && val != noreg) {
 602       iu_barrier(masm, val, tmp1, tmp2, preservation_level, decorators);
 603     }
 604   }
 605 
 606   BarrierSetAssembler::store_at(masm, decorators, type,
 607                                 base, ind_or_offs,
 608                                 val,
 609                                 tmp1, tmp2, tmp3,
 610                                 preservation_level);





 611 }
 612 
 613 void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
 614                                                                   Register dst, Register jni_env, Register obj,
 615                                                                   Register tmp, Label &slowpath) {
 616   __ block_comment("try_resolve_jobject_in_native (shenandoahgc) {");
 617 
 618   assert_different_registers(jni_env, obj, tmp);
 619 
 620   Label done;
 621 
 622   // Fast path: Reference is null (JNI tags are zero for null pointers).
 623   __ cmpdi(CCR0, obj, 0);
 624   __ beq(CCR0, done);
 625 
 626   // Resolve jobject using standard implementation.
 627   BarrierSetAssembler::try_resolve_jobject_in_native(masm, dst, jni_env, obj, tmp, slowpath);
 628 
 629   // Check whether heap is stable.
 630   __ lbz(tmp,

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


































 760 #undef __
 761 
 762 #ifdef COMPILER1
 763 
 764 #define __ ce->masm()->
 765 
 766 void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) {
 767   __ block_comment("gen_pre_barrier_stub (shenandoahgc) {");
 768 
 769   ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
 770   __ bind(*stub->entry());
 771 
 772   // GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'.
 773   // This stub is the slowpath of that function.
 774 
 775   assert(stub->pre_val()->is_register(), "pre_val must be a register");
 776   Register pre_val = stub->pre_val()->as_register();
 777 
 778   // If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()'
 779   // ("preloaded mode" of the store barrier).

   1 /*
   2  * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
   3  * Copyright (c) 2012, 2022 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "gc/shared/gcArguments.hpp"
  27 #include "gc/shared/gc_globals.hpp"
  28 #include "macroAssembler_ppc.hpp"
  29 #include "precompiled.hpp"
  30 #include "asm/macroAssembler.inline.hpp"
  31 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  32 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  33 #include "gc/shenandoah/shenandoahForwarding.hpp"
  34 #include "gc/shenandoah/shenandoahHeap.hpp"
  35 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  36 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  37 #include "gc/shenandoah/shenandoahRuntime.hpp"
  38 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  39 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  40 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  41 #include "interpreter/interpreter.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_CR(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,

 561                                  tmp1, noreg,
 562                                  preservation_level, L_handle_null);
 563 
 564     load_reference_barrier(masm, decorators,
 565                            base, ind_or_offs,
 566                            intermediate_dst,
 567                            tmp1, R0,
 568                            preservation_level);
 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 >