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; |