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 bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode();
215
216 if ((decorators & IN_NATIVE) != 0 && !is_traversal_mode) {
217 assert(access.is_oop(), "IN_NATIVE access only for oop values");
218 BarrierSetC1::load_at_resolved(access, result);
219 LIR_OprList* args = new LIR_OprList();
220 LIR_Opr addr = access.resolved_addr();
221 addr = ensure_in_register(gen, addr);
222 args->append(result);
223 args->append(addr);
224 BasicTypeList signature;
225 signature.append(T_OBJECT);
226 signature.append(T_ADDRESS);
227 LIR_Opr call_result = gen->call_runtime(&signature, args,
228 CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native),
229 objectType, NULL);
230 __ move(call_result, result);
231 } else {
232 if (ShenandoahLoadRefBarrier) {
233 LIR_Opr tmp = gen->new_register(T_OBJECT);
234 BarrierSetC1::load_at_resolved(access, tmp);
235 tmp = load_reference_barrier(access.gen(), tmp, access.resolved_addr());
236 __ move(tmp, result);
237 } else {
238 BarrierSetC1::load_at_resolved(access, result);
239 }
240 }
241
242 if (ShenandoahKeepAliveBarrier) {
243 bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
244 bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
245 bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
246 bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0 || is_traversal_mode;
247
248 if ((is_weak || is_phantom || is_anonymous) && keep_alive) {
249 // Register the value in the referent field with the pre-barrier
250 LabelObj *Lcont_anonymous;
251 if (is_anonymous) {
252 Lcont_anonymous = new LabelObj();
253 generate_referent_check(access, Lcont_anonymous);
254 }
255 pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr /* addr_opr */,
256 result /* pre_val */);
257 if (is_anonymous) {
258 __ branch_destination(Lcont_anonymous->label());
259 }
260 }
261 }
262 }
263
264 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
265 virtual OopMapSet* generate_code(StubAssembler* sasm) {
266 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
267 bs->generate_c1_pre_barrier_runtime_stub(sasm);
268 return NULL;
269 }
270 };
271
272 class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
273 virtual OopMapSet* generate_code(StubAssembler* sasm) {
274 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
275 bs->generate_c1_load_reference_barrier_runtime_stub(sasm);
276 return NULL;
277 }
278 };
279
|
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 DecoratorSet decorators = access.decorators();
207 assert((decorators & AS_RAW) == 0, "Unexpected decorator");
208 assert((decorators & AS_NO_KEEPALIVE) == 0, "Unexpected decorator");
209 BasicType type = access.type();
210 bool need_load_reference_barrier = ShenandoahBarrierSet::need_load_reference_barrier(decorators, type);
211
212 if (!need_load_reference_barrier) {
213 BarrierSetC1::load_at_resolved(access, result);
214 return;
215 }
216
217 LIRGenerator* gen = access.gen();
218
219 if (ShenandoahBarrierSet::use_native_load_reference_barrier(decorators, type)) {
220 BarrierSetC1::load_at_resolved(access, result);
221 LIR_OprList* args = new LIR_OprList();
222 LIR_Opr addr = access.resolved_addr();
223 addr = ensure_in_register(gen, addr);
224 args->append(result);
225 args->append(addr);
226 BasicTypeList signature;
227 signature.append(T_OBJECT);
228 signature.append(T_ADDRESS);
229 LIR_Opr call_result = gen->call_runtime(&signature, args,
230 CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native),
231 objectType, NULL);
232 __ move(call_result, result);
233 } else {
234 LIR_Opr tmp = gen->new_register(T_OBJECT);
235 BarrierSetC1::load_at_resolved(access, tmp);
236 tmp = load_reference_barrier(access.gen(), tmp, access.resolved_addr());
237 __ move(tmp, result);
238 }
239
240 if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
241 bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
242
243 // Register the value in the referent field with the pre-barrier
244 LabelObj *Lcont_anonymous;
245 if (is_anonymous) {
246 Lcont_anonymous = new LabelObj();
247 generate_referent_check(access, Lcont_anonymous);
248 }
249 pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr /* addr_opr */,
250 result /* pre_val */);
251 if (is_anonymous) {
252 __ branch_destination(Lcont_anonymous->label());
253 }
254 }
255 }
256
257 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
258 virtual OopMapSet* generate_code(StubAssembler* sasm) {
259 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
260 bs->generate_c1_pre_barrier_runtime_stub(sasm);
261 return NULL;
262 }
263 };
264
265 class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
266 virtual OopMapSet* generate_code(StubAssembler* sasm) {
267 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
268 bs->generate_c1_load_reference_barrier_runtime_stub(sasm);
269 return NULL;
270 }
271 };
272
|