< prev index next >

src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp

Print this page




  88 
  89     pre_val = gen->new_register(T_OBJECT);
  90 
  91     if (!addr_opr->is_address()) {
  92       assert(addr_opr->is_register(), "must be");
  93       addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
  94     }
  95     slow = new ShenandoahPreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info ? new CodeEmitInfo(info) : NULL);
  96   } else {
  97     assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
  98     assert(pre_val->is_register(), "must be");
  99     assert(pre_val->type() == T_OBJECT, "must be an object");
 100 
 101     slow = new ShenandoahPreBarrierStub(pre_val);
 102   }
 103 
 104   __ branch(lir_cond_notEqual, T_INT, slow);
 105   __ branch_destination(slow->continuation());
 106 }
 107 
 108 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj) {
 109   if (ShenandoahLoadRefBarrier) {
 110     return load_reference_barrier_impl(gen, obj);
 111   } else {
 112     return obj;
 113   }
 114 }
 115 
 116 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj) {
 117   assert(ShenandoahLoadRefBarrier, "Should be enabled");
 118 
 119   obj = ensure_in_register(gen, obj);
 120   assert(obj->is_register(), "must be a register at this point");


 121   LIR_Opr result = gen->result_register_for(obj->value_type());
 122   __ move(obj, result);
 123   LIR_Opr tmp1 = gen->new_register(T_OBJECT);
 124   LIR_Opr tmp2 = gen->new_register(T_OBJECT);
 125 
 126   LIR_Opr thrd = gen->getThreadPointer();
 127   LIR_Address* active_flag_addr =
 128     new LIR_Address(thrd,
 129                     in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
 130                     T_BYTE);
 131   // Read and check the gc-state-flag.
 132   LIR_Opr flag_val = gen->new_register(T_INT);
 133   __ load(active_flag_addr, flag_val);
 134   LIR_Opr mask = LIR_OprFact::intConst(ShenandoahHeap::HAS_FORWARDED |
 135                                        ShenandoahHeap::EVACUATION |
 136                                        ShenandoahHeap::TRAVERSAL);
 137   LIR_Opr mask_reg = gen->new_register(T_INT);
 138   __ move(mask, mask_reg);
 139 
 140   if (TwoOperandLIRForm) {
 141     __ logical_and(flag_val, mask_reg, flag_val);
 142   } else {
 143     LIR_Opr masked_flag = gen->new_register(T_INT);
 144     __ logical_and(flag_val, mask_reg, masked_flag);
 145     flag_val = masked_flag;
 146   }
 147   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
 148 
 149   CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, tmp1, tmp2);
 150   __ branch(lir_cond_notEqual, T_INT, slow);
 151   __ branch_destination(slow->continuation());
 152 
 153   return result;
 154 }
 155 
 156 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) {
 157   if (!obj->is_register()) {
 158     LIR_Opr obj_reg = gen->new_register(T_OBJECT);
 159     if (obj->is_constant()) {

 160       __ move(obj, obj_reg);
 161     } else {







 162       __ leal(obj, obj_reg);
 163     }
 164     obj = obj_reg;
 165   }
 166   return obj;
 167 }
 168 
 169 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) {
 170   if (ShenandoahStoreValEnqueueBarrier) {
 171     obj = ensure_in_register(gen, obj);
 172     pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj);
 173   }
 174   return obj;
 175 }
 176 
 177 void ShenandoahBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
 178   if (access.is_oop()) {
 179     if (ShenandoahSATBBarrier) {
 180       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */);
 181     }
 182     value = storeval_barrier(access.gen(), value, access.access_emit_info(), access.decorators());
 183   }
 184   BarrierSetC1::store_at_resolved(access, value);
 185 }
 186 








 187 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
 188   if (!access.is_oop()) {
 189     BarrierSetC1::load_at_resolved(access, result);
 190     return;
 191   }
 192 
 193   LIRGenerator* gen = access.gen();
 194 
 195   DecoratorSet decorators = access.decorators();
 196   if ((decorators & IN_NATIVE) != 0) {
 197     assert(access.is_oop(), "IN_NATIVE access only for oop values");
 198     BarrierSetC1::load_at_resolved(access, result);
 199     LIR_OprList* args = new LIR_OprList();
 200     args->append(result);
 201     BasicTypeList signature;
 202     signature.append(T_OBJECT);
 203     LIR_Opr call_result = gen->call_runtime(&signature, args,
 204                                             CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native),
 205                                             objectType, NULL);
 206     __ move(call_result, result);
 207     return;
 208   }
 209 
 210   if (ShenandoahLoadRefBarrier) {
 211     LIR_Opr tmp = gen->new_register(T_OBJECT);
 212     BarrierSetC1::load_at_resolved(access, tmp);
 213     tmp = load_reference_barrier(access.gen(), tmp);
 214     __ move(tmp, result);
 215   } else {
 216     BarrierSetC1::load_at_resolved(access, result);
 217   }
 218 
 219   if (ShenandoahKeepAliveBarrier) {
 220     bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
 221     bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
 222     bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 223     if (is_weak || is_phantom || is_anonymous) {
 224       // Register the value in the referent field with the pre-barrier
 225       LabelObj *Lcont_anonymous;
 226       if (is_anonymous) {
 227         Lcont_anonymous = new LabelObj();
 228         generate_referent_check(access, Lcont_anonymous);
 229       }
 230       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr /* addr_opr */,
 231                   result /* pre_val */);
 232       if (is_anonymous) {
 233         __ branch_destination(Lcont_anonymous->label());




  88 
  89     pre_val = gen->new_register(T_OBJECT);
  90 
  91     if (!addr_opr->is_address()) {
  92       assert(addr_opr->is_register(), "must be");
  93       addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
  94     }
  95     slow = new ShenandoahPreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info ? new CodeEmitInfo(info) : NULL);
  96   } else {
  97     assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
  98     assert(pre_val->is_register(), "must be");
  99     assert(pre_val->type() == T_OBJECT, "must be an object");
 100 
 101     slow = new ShenandoahPreBarrierStub(pre_val);
 102   }
 103 
 104   __ branch(lir_cond_notEqual, T_INT, slow);
 105   __ branch_destination(slow->continuation());
 106 }
 107 
 108 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) {
 109   if (ShenandoahLoadRefBarrier) {
 110     return load_reference_barrier_impl(gen, obj, addr);
 111   } else {
 112     return obj;
 113   }
 114 }
 115 
 116 LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) {
 117   assert(ShenandoahLoadRefBarrier, "Should be enabled");
 118 
 119   obj = ensure_in_register(gen, obj);
 120   assert(obj->is_register(), "must be a register at this point");
 121   addr = ensure_in_register(gen, addr);
 122   assert(addr->is_register(), "must be a register at this point");
 123   LIR_Opr result = gen->result_register_for(obj->value_type());
 124   __ move(obj, result);
 125   LIR_Opr tmp1 = gen->new_register(T_OBJECT);
 126   LIR_Opr tmp2 = gen->new_register(T_OBJECT);
 127 
 128   LIR_Opr thrd = gen->getThreadPointer();
 129   LIR_Address* active_flag_addr =
 130     new LIR_Address(thrd,
 131                     in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
 132                     T_BYTE);
 133   // Read and check the gc-state-flag.
 134   LIR_Opr flag_val = gen->new_register(T_INT);
 135   __ load(active_flag_addr, flag_val);
 136   LIR_Opr mask = LIR_OprFact::intConst(ShenandoahHeap::HAS_FORWARDED |
 137                                        ShenandoahHeap::EVACUATION |
 138                                        ShenandoahHeap::TRAVERSAL);
 139   LIR_Opr mask_reg = gen->new_register(T_INT);
 140   __ move(mask, mask_reg);
 141 
 142   if (TwoOperandLIRForm) {
 143     __ logical_and(flag_val, mask_reg, flag_val);
 144   } else {
 145     LIR_Opr masked_flag = gen->new_register(T_INT);
 146     __ logical_and(flag_val, mask_reg, masked_flag);
 147     flag_val = masked_flag;
 148   }
 149   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
 150 
 151   CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, addr, result, tmp1, tmp2);
 152   __ branch(lir_cond_notEqual, T_INT, slow);
 153   __ branch_destination(slow->continuation());
 154 
 155   return result;
 156 }
 157 
 158 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) {
 159   if (!obj->is_register()) {
 160     LIR_Opr obj_reg;
 161     if (obj->is_constant()) {
 162       obj_reg = gen->new_register(T_OBJECT);
 163       __ move(obj, obj_reg);
 164     } else {
 165 #ifdef AARCH64
 166       // AArch64 expects double-size register.
 167       obj_reg = gen->new_pointer_register();
 168 #else
 169       // x86 expects single-size register.
 170       obj_reg = gen->new_register(T_OBJECT);
 171 #endif
 172       __ leal(obj, obj_reg);
 173     }
 174     obj = obj_reg;
 175   }
 176   return obj;
 177 }
 178 
 179 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) {
 180   if (ShenandoahStoreValEnqueueBarrier) {
 181     obj = ensure_in_register(gen, obj);
 182     pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj);
 183   }
 184   return obj;
 185 }
 186 
 187 void ShenandoahBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
 188   if (access.is_oop()) {
 189     if (ShenandoahSATBBarrier) {
 190       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */);
 191     }
 192     value = storeval_barrier(access.gen(), value, access.access_emit_info(), access.decorators());
 193   }
 194   BarrierSetC1::store_at_resolved(access, value);
 195 }
 196 
 197 LIR_Opr ShenandoahBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
 198   // We must resolve in register when patching. This is to avoid
 199   // having a patch area in the load barrier stub, since the call
 200   // into the runtime to patch will not have the proper oop map.
 201   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 }
 204 
 205 void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
 206   if (!access.is_oop()) {
 207     BarrierSetC1::load_at_resolved(access, result);
 208     return;
 209   }
 210 
 211   LIRGenerator* gen = access.gen();
 212 
 213   DecoratorSet decorators = access.decorators();
 214   if ((decorators & IN_NATIVE) != 0) {
 215     assert(access.is_oop(), "IN_NATIVE access only for oop values");
 216     BarrierSetC1::load_at_resolved(access, result);
 217     LIR_OprList* args = new LIR_OprList();
 218     args->append(result);
 219     BasicTypeList signature;
 220     signature.append(T_OBJECT);
 221     LIR_Opr call_result = gen->call_runtime(&signature, args,
 222                                             CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native),
 223                                             objectType, NULL);
 224     __ move(call_result, result);
 225     return;
 226   }
 227 
 228   if (ShenandoahLoadRefBarrier) {
 229     LIR_Opr tmp = gen->new_register(T_OBJECT);
 230     BarrierSetC1::load_at_resolved(access, tmp);
 231     tmp = load_reference_barrier(access.gen(), tmp, access.resolved_addr());
 232     __ move(tmp, result);
 233   } else {
 234     BarrierSetC1::load_at_resolved(access, result);
 235   }
 236 
 237   if (ShenandoahKeepAliveBarrier) {
 238     bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
 239     bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
 240     bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 241     if (is_weak || is_phantom || is_anonymous) {
 242       // Register the value in the referent field with the pre-barrier
 243       LabelObj *Lcont_anonymous;
 244       if (is_anonymous) {
 245         Lcont_anonymous = new LabelObj();
 246         generate_referent_check(access, Lcont_anonymous);
 247       }
 248       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr /* addr_opr */,
 249                   result /* pre_val */);
 250       if (is_anonymous) {
 251         __ branch_destination(Lcont_anonymous->label());


< prev index next >