< prev index next >

src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp

Print this page
rev 56437 : 8231583: Shenandoah: Fix register clash in SBSA::resolve_forwarding_pointer() borrowing


 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 


< prev index next >