src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp
changeset 54423 6c0ab8bd8da5
parent 52925 9c18c9d839d3
child 54766 1321f8cf9de5
equal deleted inserted replaced
54422:f562f8318ebd 54423:6c0ab8bd8da5
    44 void ShenandoahPreBarrierStub::emit_code(LIR_Assembler* ce) {
    44 void ShenandoahPreBarrierStub::emit_code(LIR_Assembler* ce) {
    45   ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
    45   ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
    46   bs->gen_pre_barrier_stub(ce, this);
    46   bs->gen_pre_barrier_stub(ce, this);
    47 }
    47 }
    48 
    48 
    49 void ShenandoahWriteBarrierStub::emit_code(LIR_Assembler* ce) {
    49 void ShenandoahLoadReferenceBarrierStub::emit_code(LIR_Assembler* ce) {
    50   ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
    50   ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
    51   bs->gen_write_barrier_stub(ce, this);
    51   bs->gen_load_reference_barrier_stub(ce, this);
    52 }
    52 }
    53 
    53 
    54 void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) {
    54 void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) {
    55   // First we test whether marking is in progress.
    55   // First we test whether marking is in progress.
    56   BasicType flag_type;
    56   BasicType flag_type;
   103 
   103 
   104   __ branch(lir_cond_notEqual, T_INT, slow);
   104   __ branch(lir_cond_notEqual, T_INT, slow);
   105   __ branch_destination(slow->continuation());
   105   __ branch_destination(slow->continuation());
   106 }
   106 }
   107 
   107 
   108 LIR_Opr ShenandoahBarrierSetC1::read_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
   108 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
   109   if (UseShenandoahGC && ShenandoahReadBarrier) {
   109   if (ShenandoahLoadRefBarrier) {
   110     return read_barrier_impl(gen, obj, info, need_null_check);
   110     return load_reference_barrier_impl(gen, obj, info, need_null_check);
   111   } else {
   111   } else {
   112     return obj;
   112     return obj;
   113   }
   113   }
   114 }
   114 }
   115 
   115 
   116 LIR_Opr ShenandoahBarrierSetC1::read_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
   116 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
   117   assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier), "Should be enabled");
   117   assert(ShenandoahLoadRefBarrier, "Should be enabled");
   118   LabelObj* done = new LabelObj();
       
   119   LIR_Opr result = gen->new_register(T_OBJECT);
       
   120   __ move(obj, result);
       
   121   if (need_null_check) {
       
   122     __ cmp(lir_cond_equal, result, LIR_OprFact::oopConst(NULL));
       
   123     __ branch(lir_cond_equal, T_LONG, done->label());
       
   124   }
       
   125   LIR_Address* brooks_ptr_address = gen->generate_address(result, ShenandoahBrooksPointer::byte_offset(), T_ADDRESS);
       
   126   __ load(brooks_ptr_address, result, info ? new CodeEmitInfo(info) : NULL, lir_patch_none);
       
   127 
       
   128   __ branch_destination(done->label());
       
   129   return result;
       
   130 }
       
   131 
       
   132 LIR_Opr ShenandoahBarrierSetC1::write_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
       
   133   if (UseShenandoahGC && ShenandoahWriteBarrier) {
       
   134     return write_barrier_impl(gen, obj, info, need_null_check);
       
   135   } else {
       
   136     return obj;
       
   137   }
       
   138 }
       
   139 
       
   140 LIR_Opr ShenandoahBarrierSetC1::write_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
       
   141   assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
       
   142 
   118 
   143   obj = ensure_in_register(gen, obj);
   119   obj = ensure_in_register(gen, obj);
   144   assert(obj->is_register(), "must be a register at this point");
   120   assert(obj->is_register(), "must be a register at this point");
   145   LIR_Opr result = gen->new_register(T_OBJECT);
   121   LIR_Opr result = gen->new_register(T_OBJECT);
   146   __ move(obj, result);
   122   __ move(obj, result);
   166     __ logical_and(flag_val, mask_reg, masked_flag);
   142     __ logical_and(flag_val, mask_reg, masked_flag);
   167     flag_val = masked_flag;
   143     flag_val = masked_flag;
   168   }
   144   }
   169   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
   145   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
   170 
   146 
   171   CodeStub* slow = new ShenandoahWriteBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
   147   CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
   172   __ branch(lir_cond_notEqual, T_INT, slow);
   148   __ branch(lir_cond_notEqual, T_INT, slow);
   173   __ branch_destination(slow->continuation());
   149   __ branch_destination(slow->continuation());
   174 
   150 
   175   return result;
   151   return result;
   176 }
   152 }
   187   }
   163   }
   188   return obj;
   164   return obj;
   189 }
   165 }
   190 
   166 
   191 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) {
   167 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) {
   192   bool need_null_check = (decorators & IS_NOT_NULL) == 0;
       
   193   if (ShenandoahStoreValEnqueueBarrier) {
   168   if (ShenandoahStoreValEnqueueBarrier) {
   194     obj = write_barrier_impl(gen, obj, info, need_null_check);
   169     obj = ensure_in_register(gen, obj);
   195     pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj);
   170     pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj);
   196   }
   171   }
   197   if (ShenandoahStoreValReadBarrier) {
       
   198     obj = read_barrier_impl(gen, obj, info, true /*need_null_check*/);
       
   199   }
       
   200   return obj;
   172   return obj;
   201 }
       
   202 
       
   203 LIR_Opr ShenandoahBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
       
   204   DecoratorSet decorators = access.decorators();
       
   205   bool is_array = (decorators & IS_ARRAY) != 0;
       
   206   bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
       
   207 
       
   208   bool is_write = (decorators & ACCESS_WRITE) != 0;
       
   209   bool needs_null_check = (decorators & IS_NOT_NULL) == 0;
       
   210 
       
   211   LIR_Opr base = access.base().item().result();
       
   212   LIR_Opr offset = access.offset().opr();
       
   213   LIRGenerator* gen = access.gen();
       
   214 
       
   215   if (is_write) {
       
   216     base = write_barrier(gen, base, access.access_emit_info(), needs_null_check);
       
   217   } else {
       
   218     base = read_barrier(gen, base, access.access_emit_info(), needs_null_check);
       
   219   }
       
   220 
       
   221   LIR_Opr addr_opr;
       
   222   if (is_array) {
       
   223     addr_opr = LIR_OprFact::address(gen->emit_array_address(base, offset, access.type()));
       
   224   } else if (needs_patching) {
       
   225     // we need to patch the offset in the instruction so don't allow
       
   226     // generate_address to try to be smart about emitting the -1.
       
   227     // Otherwise the patching code won't know how to find the
       
   228     // instruction to patch.
       
   229     addr_opr = LIR_OprFact::address(new LIR_Address(base, PATCHED_ADDR, access.type()));
       
   230   } else {
       
   231     addr_opr = LIR_OprFact::address(gen->generate_address(base, offset, 0, 0, access.type()));
       
   232   }
       
   233 
       
   234   if (resolve_in_register) {
       
   235     LIR_Opr resolved_addr = gen->new_pointer_register();
       
   236     __ leal(addr_opr, resolved_addr);
       
   237     resolved_addr = LIR_OprFact::address(new LIR_Address(resolved_addr, access.type()));
       
   238     return resolved_addr;
       
   239   } else {
       
   240     return addr_opr;
       
   241   }
       
   242 }
   173 }
   243 
   174 
   244 void ShenandoahBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
   175 void ShenandoahBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
   245   if (access.is_oop()) {
   176   if (access.is_oop()) {
   246     if (ShenandoahSATBBarrier) {
   177     if (ShenandoahSATBBarrier) {
   250   }
   181   }
   251   BarrierSetC1::store_at_resolved(access, value);
   182   BarrierSetC1::store_at_resolved(access, value);
   252 }
   183 }
   253 
   184 
   254 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
   185 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
   255   BarrierSetC1::load_at_resolved(access, result);
   186   if (!access.is_oop()) {
       
   187     BarrierSetC1::load_at_resolved(access, result);
       
   188     return;
       
   189   }
       
   190 
       
   191   LIRGenerator *gen = access.gen();
       
   192 
       
   193   if (ShenandoahLoadRefBarrier) {
       
   194     LIR_Opr tmp = gen->new_register(T_OBJECT);
       
   195     BarrierSetC1::load_at_resolved(access, tmp);
       
   196     tmp = load_reference_barrier(access.gen(), tmp, access.access_emit_info(), true);
       
   197     __ move(tmp, result);
       
   198   } else {
       
   199     BarrierSetC1::load_at_resolved(access, result);
       
   200   }
   256 
   201 
   257   if (ShenandoahKeepAliveBarrier) {
   202   if (ShenandoahKeepAliveBarrier) {
   258     DecoratorSet decorators = access.decorators();
   203     DecoratorSet decorators = access.decorators();
   259     bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   204     bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
   260     bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
   205     bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
   261     bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
   206     bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
   262     LIRGenerator *gen = access.gen();
   207     if (is_weak || is_phantom || is_anonymous) {
   263     if (access.is_oop() && (is_weak || is_phantom || is_anonymous)) {
       
   264       // Register the value in the referent field with the pre-barrier
   208       // Register the value in the referent field with the pre-barrier
   265       LabelObj *Lcont_anonymous;
   209       LabelObj *Lcont_anonymous;
   266       if (is_anonymous) {
   210       if (is_anonymous) {
   267         Lcont_anonymous = new LabelObj();
   211         Lcont_anonymous = new LabelObj();
   268         generate_referent_check(access, Lcont_anonymous);
   212         generate_referent_check(access, Lcont_anonymous);
   274       }
   218       }
   275     }
   219     }
   276   }
   220   }
   277 }
   221 }
   278 
   222 
   279 LIR_Opr ShenandoahBarrierSetC1::atomic_add_at_resolved(LIRAccess& access, LIRItem& value) {
       
   280   return BarrierSetC1::atomic_add_at_resolved(access, value);
       
   281 }
       
   282 
       
   283 LIR_Opr ShenandoahBarrierSetC1::resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj) {
       
   284   bool is_write = decorators & ACCESS_WRITE;
       
   285   if (is_write) {
       
   286     return write_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
       
   287   } else {
       
   288     return read_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
       
   289   }
       
   290 }
       
   291 
       
   292 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
   223 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
   293   virtual OopMapSet* generate_code(StubAssembler* sasm) {
   224   virtual OopMapSet* generate_code(StubAssembler* sasm) {
   294     ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
   225     ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
   295     bs->generate_c1_pre_barrier_runtime_stub(sasm);
   226     bs->generate_c1_pre_barrier_runtime_stub(sasm);
   296     return NULL;
   227     return NULL;