25 #include "gc/g1/satbMarkQueue.hpp"
26 #include "gc/shenandoah/brooksPointer.hpp"
27 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
28 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
29 #include "gc/shenandoah/shenandoahHeap.hpp"
30 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
32 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
33
34 #ifdef ASSERT
35 #define __ gen->lir(__FILE__, __LINE__)->
36 #else
37 #define __ gen->lir()->
38 #endif
39
40 void ShenandoahPreBarrierStub::emit_code(LIR_Assembler* ce) {
41 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
42 bs->gen_pre_barrier_stub(ce, this);
43 }
44
45 void ShenandoahBarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr, LIR_Opr pre_val) {
46 LIRGenerator* gen = access.gen();
47 CodeEmitInfo* info = access.access_emit_info();
48 DecoratorSet decorators = access.decorators();
49
50 // First we test whether marking is in progress.
51 BasicType flag_type;
52 bool patch = (decorators & C1_NEEDS_PATCHING) != 0;
53 bool do_load = pre_val == LIR_OprFact::illegalOpr;
54 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
55 flag_type = T_INT;
56 } else {
57 guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
58 "Assumption");
59 // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
60 // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
61 flag_type = T_BOOLEAN;
62 }
63 LIR_Opr thrd = gen->getThreadPointer();
64 LIR_Address* mark_active_flag_addr =
188 __ branch(lir_cond_equal, T_LONG, done->label());
189 }
190 LIR_Address* brooks_ptr_address = gen->generate_address(result, BrooksPointer::byte_offset(), T_ADDRESS);
191 __ load(brooks_ptr_address, result, info ? new CodeEmitInfo(info) : NULL, lir_patch_none);
192
193 __ branch_destination(done->label());
194 return result;
195 }
196
197 LIR_Opr ShenandoahBarrierSetC1::write_barrier(LIRAccess& access, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
198 if (UseShenandoahGC && ShenandoahWriteBarrier) {
199 return write_barrier_impl(access, obj, info, need_null_check);
200 } else {
201 return obj;
202 }
203 }
204
205 LIR_Opr ShenandoahBarrierSetC1::write_barrier_impl(LIRAccess& access, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
206 assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
207 LIRGenerator* gen = access.gen();
208 LIR_Opr result = gen->new_register(T_OBJECT);
209
210 obj = ensure_in_register(access, obj);
211 assert(obj->is_register(), "must be a register at this point");
212
213 __ shenandoah_wb(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
214 return result;
215 }
216
217 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRAccess& access, LIR_Opr obj) {
218 if (!obj->is_register()) {
219 LIRGenerator* gen = access.gen();
220 LIR_Opr obj_reg = gen->new_register(T_OBJECT);
221 if (obj->is_constant()) {
222 __ move(obj, obj_reg);
223 } else {
224 __ leal(obj, obj_reg);
225 }
226 obj = obj_reg;
227 }
228 return obj;
229 }
230
231 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRAccess& access, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
232 LIRGenerator* gen = access.gen();
233 if (UseShenandoahGC) {
|
25 #include "gc/g1/satbMarkQueue.hpp"
26 #include "gc/shenandoah/brooksPointer.hpp"
27 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
28 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
29 #include "gc/shenandoah/shenandoahHeap.hpp"
30 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
32 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
33
34 #ifdef ASSERT
35 #define __ gen->lir(__FILE__, __LINE__)->
36 #else
37 #define __ gen->lir()->
38 #endif
39
40 void ShenandoahPreBarrierStub::emit_code(LIR_Assembler* ce) {
41 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
42 bs->gen_pre_barrier_stub(ce, this);
43 }
44
45 void ShenandoahWriteBarrierStub::emit_code(LIR_Assembler* ce) {
46 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
47 bs->gen_write_barrier_stub(ce, this);
48 }
49
50 void ShenandoahBarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr, LIR_Opr pre_val) {
51 LIRGenerator* gen = access.gen();
52 CodeEmitInfo* info = access.access_emit_info();
53 DecoratorSet decorators = access.decorators();
54
55 // First we test whether marking is in progress.
56 BasicType flag_type;
57 bool patch = (decorators & C1_NEEDS_PATCHING) != 0;
58 bool do_load = pre_val == LIR_OprFact::illegalOpr;
59 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
60 flag_type = T_INT;
61 } else {
62 guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
63 "Assumption");
64 // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
65 // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
66 flag_type = T_BOOLEAN;
67 }
68 LIR_Opr thrd = gen->getThreadPointer();
69 LIR_Address* mark_active_flag_addr =
193 __ branch(lir_cond_equal, T_LONG, done->label());
194 }
195 LIR_Address* brooks_ptr_address = gen->generate_address(result, BrooksPointer::byte_offset(), T_ADDRESS);
196 __ load(brooks_ptr_address, result, info ? new CodeEmitInfo(info) : NULL, lir_patch_none);
197
198 __ branch_destination(done->label());
199 return result;
200 }
201
202 LIR_Opr ShenandoahBarrierSetC1::write_barrier(LIRAccess& access, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
203 if (UseShenandoahGC && ShenandoahWriteBarrier) {
204 return write_barrier_impl(access, obj, info, need_null_check);
205 } else {
206 return obj;
207 }
208 }
209
210 LIR_Opr ShenandoahBarrierSetC1::write_barrier_impl(LIRAccess& access, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
211 assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
212 LIRGenerator* gen = access.gen();
213
214 obj = ensure_in_register(access, obj);
215 assert(obj->is_register(), "must be a register at this point");
216 LIR_Opr result = gen->new_register(T_OBJECT);
217 __ move(obj, result);
218
219 LIR_Opr thrd = gen->getThreadPointer();
220 LIR_Address* active_flag_addr =
221 new LIR_Address(thrd,
222 in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
223 T_BYTE);
224 // Read the marking-in-progress flag.
225 LIR_Opr flag_val = gen->new_register(T_INT);
226 __ load(active_flag_addr, flag_val);
227 __ logical_and(flag_val,
228 LIR_OprFact::intConst(ShenandoahHeap::HAS_FORWARDED |
229 ShenandoahHeap::EVACUATION |
230 ShenandoahHeap::TRAVERSAL),
231 flag_val);
232 __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
233
234 CodeStub* slow = new ShenandoahWriteBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
235 __ branch(lir_cond_notEqual, T_INT, slow);
236 __ branch_destination(slow->continuation());
237
238 return result;
239 }
240
241 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRAccess& access, LIR_Opr obj) {
242 if (!obj->is_register()) {
243 LIRGenerator* gen = access.gen();
244 LIR_Opr obj_reg = gen->new_register(T_OBJECT);
245 if (obj->is_constant()) {
246 __ move(obj, obj_reg);
247 } else {
248 __ leal(obj, obj_reg);
249 }
250 obj = obj_reg;
251 }
252 return obj;
253 }
254
255 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRAccess& access, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
256 LIRGenerator* gen = access.gen();
257 if (UseShenandoahGC) {
|