src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp
changeset 58946 83810b7d12e7
parent 58694 199ee1bf9b3b
child 58985 5606867a5e6e
equal deleted inserted replaced
58945:a3b046720c3b 58946:83810b7d12e7
    23 
    23 
    24 #include "precompiled.hpp"
    24 #include "precompiled.hpp"
    25 #include "c1/c1_IR.hpp"
    25 #include "c1/c1_IR.hpp"
    26 #include "gc/shared/satbMarkQueue.hpp"
    26 #include "gc/shared/satbMarkQueue.hpp"
    27 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
    27 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
       
    28 #include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
    28 #include "gc/shenandoah/shenandoahHeap.hpp"
    29 #include "gc/shenandoah/shenandoahHeap.hpp"
    29 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
    30 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
    30 #include "gc/shenandoah/shenandoahRuntime.hpp"
    31 #include "gc/shenandoah/shenandoahRuntime.hpp"
    31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
    32 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
    32 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
    33 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
   201   const bool patch_before_barrier = access.is_oop() && (access.decorators() & C1_NEEDS_PATCHING) != 0;
   202   const bool patch_before_barrier = access.is_oop() && (access.decorators() & C1_NEEDS_PATCHING) != 0;
   202   return BarrierSetC1::resolve_address(access, resolve_in_register || patch_before_barrier);
   203   return BarrierSetC1::resolve_address(access, resolve_in_register || patch_before_barrier);
   203 }
   204 }
   204 
   205 
   205 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
   206 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
       
   207   // 1: non-reference load, no additional barrier is needed
   206   if (!access.is_oop()) {
   208   if (!access.is_oop()) {
   207     BarrierSetC1::load_at_resolved(access, result);
   209     BarrierSetC1::load_at_resolved(access, result);
   208     return;
   210     return;
   209   }
   211   }
   210 
   212 
   211   LIRGenerator* gen = access.gen();
   213   LIRGenerator* gen = access.gen();
   212 
       
   213   DecoratorSet decorators = access.decorators();
   214   DecoratorSet decorators = access.decorators();
   214   bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode();
   215 
   215 
   216   // 2: load a reference from src location and apply LRB if ShenandoahLoadRefBarrier is set
   216   if ((decorators & IN_NATIVE) != 0 && !is_traversal_mode) {
   217   if (ShenandoahLoadRefBarrier) {
   217     assert(access.is_oop(), "IN_NATIVE access only for oop values");
   218     // Native barrier is for concurrent root processing
   218     BarrierSetC1::load_at_resolved(access, result);
   219     bool in_native = (decorators & IN_NATIVE) != 0;
   219     LIR_OprList* args = new LIR_OprList();
   220     if (in_native && ShenandoahConcurrentRoots::can_do_concurrent_roots()) {
   220     LIR_Opr addr = access.resolved_addr();
   221       BarrierSetC1::load_at_resolved(access, result);
   221     addr = ensure_in_register(gen, addr);
   222       LIR_OprList* args = new LIR_OprList();
   222     args->append(result);
   223       LIR_Opr addr = access.resolved_addr();
   223     args->append(addr);
   224       addr = ensure_in_register(gen, addr);
   224     BasicTypeList signature;
   225       args->append(result);
   225     signature.append(T_OBJECT);
   226       args->append(addr);
   226     signature.append(T_ADDRESS);
   227       BasicTypeList signature;
   227     LIR_Opr call_result = gen->call_runtime(&signature, args,
   228       signature.append(T_OBJECT);
   228                                             CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native),
   229       signature.append(T_ADDRESS);
   229                                             objectType, NULL);
   230       LIR_Opr call_result = gen->call_runtime(&signature, args,
   230     __ move(call_result, result);
   231                                               CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native),
   231   } else {
   232                                               objectType, NULL);
   232     if (ShenandoahLoadRefBarrier) {
   233       __ move(call_result, result);
       
   234     } else {
   233       LIR_Opr tmp = gen->new_register(T_OBJECT);
   235       LIR_Opr tmp = gen->new_register(T_OBJECT);
   234       BarrierSetC1::load_at_resolved(access, tmp);
   236       BarrierSetC1::load_at_resolved(access, tmp);
   235       tmp = load_reference_barrier(access.gen(), tmp, access.resolved_addr());
   237       tmp = load_reference_barrier(gen, tmp, access.resolved_addr());
   236       __ move(tmp, result);
   238       __ move(tmp, result);
   237     } else {
   239     }
   238       BarrierSetC1::load_at_resolved(access, result);
   240   } else {
   239     }
   241     BarrierSetC1::load_at_resolved(access, result);
   240   }
   242   }
   241 
   243 
       
   244   // 3: apply keep-alive barrier if ShenandoahKeepAliveBarrier is set
   242   if (ShenandoahKeepAliveBarrier) {
   245   if (ShenandoahKeepAliveBarrier) {
   243     bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   246     bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   244     bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
   247     bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
   245     bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
   248     bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
       
   249     bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode();
   246     bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0 || is_traversal_mode;
   250     bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0 || is_traversal_mode;
   247 
   251 
   248     if ((is_weak || is_phantom || is_anonymous) && keep_alive) {
   252     if ((is_weak || is_phantom || is_anonymous) && keep_alive) {
   249       // Register the value in the referent field with the pre-barrier
   253       // Register the value in the referent field with the pre-barrier
   250       LabelObj *Lcont_anonymous;
   254       LabelObj *Lcont_anonymous;
   251       if (is_anonymous) {
   255       if (is_anonymous) {
   252         Lcont_anonymous = new LabelObj();
   256         Lcont_anonymous = new LabelObj();
   253         generate_referent_check(access, Lcont_anonymous);
   257         generate_referent_check(access, Lcont_anonymous);
   254       }
   258       }
   255       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr /* addr_opr */,
   259       pre_barrier(gen, access.access_emit_info(), decorators, LIR_OprFact::illegalOpr /* addr_opr */,
   256                   result /* pre_val */);
   260                   result /* pre_val */);
   257       if (is_anonymous) {
   261       if (is_anonymous) {
   258         __ branch_destination(Lcont_anonymous->label());
   262         __ branch_destination(Lcont_anonymous->label());
   259       }
   263       }
   260     }
   264     }
   261   }
   265  }
   262 }
   266 }
   263 
   267 
   264 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
   268 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
   265   virtual OopMapSet* generate_code(StubAssembler* sasm) {
   269   virtual OopMapSet* generate_code(StubAssembler* sasm) {
   266     ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
   270     ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();