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