230 #endif
231 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), 2);
232 } else {
233 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), LP64_ONLY(c_rarg0) NOT_LP64(pre_val), thread);
234 }
235
236 NOT_LP64( __ pop(thread); )
237
238 // save the live input values
239 if (pre_val != rax)
240 __ pop(pre_val);
241
242 if (obj != noreg && obj != rax)
243 __ pop(obj);
244
245 if(tosca_live) __ pop(rax);
246
247 __ bind(done);
248 }
249
250 void ShenandoahBarrierSetAssembler::resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp) {
251 assert(ShenandoahCASBarrier, "should be enabled");
252 Label is_null;
253 __ testptr(dst, dst);
254 __ jcc(Assembler::zero, is_null);
255 resolve_forward_pointer_not_null(masm, dst, tmp);
256 __ bind(is_null);
257 }
258
259 void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp) {
260 assert(ShenandoahCASBarrier || ShenandoahLoadRefBarrier, "should be enabled");
261 // The below loads the mark word, checks if the lowest two bits are
262 // set, and if so, clear the lowest two bits and copy the result
263 // to dst. Otherwise it leaves dst alone.
264 // Implementing this is surprisingly awkward. I do it here by:
265 // - Inverting the mark word
266 // - Test lowest two bits == 0
267 // - If so, set the lowest two bits
268 // - Invert the result back, and copy to dst
269
270 bool borrow_reg = (tmp == noreg);
271 if (borrow_reg) {
272 // No free registers available. Make one useful.
273 tmp = LP64_ONLY(rscratch1) NOT_LP64(rdx);
274 __ push(tmp);
275 }
276
277 Label done;
278 __ movptr(tmp, Address(dst, oopDesc::mark_offset_in_bytes()));
279 __ notptr(tmp);
280 __ testb(tmp, markWord::marked_value);
281 __ jccb(Assembler::notZero, done);
282 __ orptr(tmp, markWord::marked_value);
283 __ notptr(tmp);
284 __ mov(dst, tmp);
285 __ bind(done);
286
287 if (borrow_reg) {
288 __ pop(tmp);
289 }
290 }
291
292
293 void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembler* masm, Register dst) {
294 assert(ShenandoahLoadRefBarrier, "Should be enabled");
295
296 Label done;
297
298 #ifdef _LP64
299 Register thread = r15_thread;
300 #else
301 Register thread = rcx;
302 if (thread == dst) {
303 thread = rbx;
304 }
305 __ push(thread);
306 __ get_thread(thread);
307 #endif
308 assert_different_registers(dst, thread);
309
|
230 #endif
231 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), 2);
232 } else {
233 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), LP64_ONLY(c_rarg0) NOT_LP64(pre_val), thread);
234 }
235
236 NOT_LP64( __ pop(thread); )
237
238 // save the live input values
239 if (pre_val != rax)
240 __ pop(pre_val);
241
242 if (obj != noreg && obj != rax)
243 __ pop(obj);
244
245 if(tosca_live) __ pop(rax);
246
247 __ bind(done);
248 }
249
250 void ShenandoahBarrierSetAssembler::resolve_forward_pointer(MacroAssembler* masm, Register dst) {
251 assert(ShenandoahCASBarrier, "should be enabled");
252 Label is_null;
253 __ testptr(dst, dst);
254 __ jcc(Assembler::zero, is_null);
255 resolve_forward_pointer_not_null(masm, dst);
256 __ bind(is_null);
257 }
258
259 void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst) {
260 assert(ShenandoahCASBarrier || ShenandoahLoadRefBarrier, "should be enabled");
261 // The below loads the mark word, checks if the lowest two bits are
262 // set, and if so, clear the lowest two bits and copy the result
263 // to dst. Otherwise it leaves dst alone.
264 // Implementing this is surprisingly awkward. I do it here by:
265 // - Inverting the mark word
266 // - Test lowest two bits == 0
267 // - If so, set the lowest two bits
268 // - Invert the result back, and copy to dst
269
270 // No free registers available. Make one useful.
271 Register tmp = rscratch1;
272 tmp = LP64_ONLY(rscratch1) NOT_LP64(rdx);
273 if (tmp == dst) {
274 tmp = LP64_ONLY(rscratch2) NOT_LP64(rcx);
275 }
276 __ push(tmp);
277
278 assert_different_registers(dst, tmp);
279
280 Label done;
281 __ movptr(tmp, Address(dst, oopDesc::mark_offset_in_bytes()));
282 __ notptr(tmp);
283 __ testb(tmp, markWord::marked_value);
284 __ jccb(Assembler::notZero, done);
285 __ orptr(tmp, markWord::marked_value);
286 __ notptr(tmp);
287 __ mov(dst, tmp);
288 __ bind(done);
289
290 __ pop(tmp);
291 }
292
293
294 void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembler* masm, Register dst) {
295 assert(ShenandoahLoadRefBarrier, "Should be enabled");
296
297 Label done;
298
299 #ifdef _LP64
300 Register thread = r15_thread;
301 #else
302 Register thread = rcx;
303 if (thread == dst) {
304 thread = rbx;
305 }
306 __ push(thread);
307 __ get_thread(thread);
308 #endif
309 assert_different_registers(dst, thread);
310
|