< prev index next >

src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp

Print this page
*** 188,11 ***
    __ jcc(Assembler::equal, done);
  
    // Can we store original value in the thread's buffer?
    // Is index == 0?
    // (The index field is typed as size_t.)
- 
    __ movptr(tmp, index);                   // tmp := *index_adr
    __ cmpptr(tmp, 0);                       // tmp == 0?
    __ jcc(Assembler::equal, runtime);       // If yes, goto runtime
  
    __ subptr(tmp, wordSize);                // tmp := tmp - wordSize
--- 188,10 ---

*** 202,18 ***
    // Record the previous value
    __ movptr(Address(tmp, 0), pre_val);
    __ jmp(done);
  
    __ bind(runtime);
!   // save the live input values
!   if(tosca_live) __ push(rax);
! 
!   if (obj != noreg && obj != rax)
!     __ push(obj);
! 
!   if (pre_val != rax)
!     __ push(pre_val);
  
    // Calling the runtime using the regular call_VM_leaf mechanism generates
    // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
    // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
    //
--- 201,22 ---
    // Record the previous value
    __ movptr(Address(tmp, 0), pre_val);
    __ jmp(done);
  
    __ bind(runtime);
!   // Barriers might be emitted when converting between (scalarized) calling conventions for inline
!   // types. Save all argument registers before calling into the runtime.
!   __ pusha();
!   __ subptr(rsp, 64);
!   __ movdbl(Address(rsp, 0),  j_farg0);
!   __ movdbl(Address(rsp, 8),  j_farg1);
!   __ movdbl(Address(rsp, 16), j_farg2);
!   __ movdbl(Address(rsp, 24), j_farg3);
+   __ movdbl(Address(rsp, 32), j_farg4);
+   __ movdbl(Address(rsp, 40), j_farg5);
+   __ movdbl(Address(rsp, 48), j_farg6);
+   __ movdbl(Address(rsp, 56), j_farg7);
  
    // Calling the runtime using the regular call_VM_leaf mechanism generates
    // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
    // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
    //

*** 223,12 ***
    //
    // Expanding the call directly bypasses the generation of the check.
    // So when we do not have have a full interpreter frame on the stack
    // expand_call should be passed true.
  
-   NOT_LP64( __ push(thread); )
- 
    if (expand_call) {
      LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
  #ifdef _LP64
      if (c_rarg1 != thread) {
        __ mov(c_rarg1, thread);
--- 226,10 ---

*** 243,20 ***
      __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
    } else {
      __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    }
  
!   NOT_LP64( __ pop(thread); )
! 
!   // save the live input values
!   if (pre_val != rax)
!     __ pop(pre_val);
! 
!   if (obj != noreg && obj != rax)
!     __ pop(obj);
! 
!   if(tosca_live) __ pop(rax);
  
    __ bind(done);
  }
  
  void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
--- 244,21 ---
      __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
    } else {
      __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    }
  
!   // Restore registers
!   __ movdbl(j_farg0, Address(rsp, 0));
!   __ movdbl(j_farg1, Address(rsp, 8));
!   __ movdbl(j_farg2, Address(rsp, 16));
!   __ movdbl(j_farg3, Address(rsp, 24));
!   __ movdbl(j_farg4, Address(rsp, 32));
!   __ movdbl(j_farg5, Address(rsp, 40));
!   __ movdbl(j_farg6, Address(rsp, 48));
!   __ movdbl(j_farg7, Address(rsp, 56));
!   __ addptr(rsp, 64);
+   __ popa();
  
    __ bind(done);
  }
  
  void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,

*** 325,34 ***
    __ addptr(tmp2, buffer);
    __ movptr(Address(tmp2, 0), card_addr);
    __ jmp(done);
  
    __ bind(runtime);
!   // save the live input values
!   __ push(store_addr);
  #ifdef _LP64
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, r15_thread);
  #else
    __ push(thread);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
    __ pop(thread);
  #endif
!   __ pop(store_addr);
  
    __ bind(done);
  }
  
  void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
!                                          Address dst, Register val, Register tmp1, Register tmp2) {
    bool in_heap = (decorators & IN_HEAP) != 0;
    bool as_normal = (decorators & AS_NORMAL) != 0;
!   assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
  
!   bool needs_pre_barrier = as_normal;
    bool needs_post_barrier = val != noreg && in_heap;
  
!   Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);
    Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
    // flatten object address if needed
    // We do it regardless of precise because we need the registers
    if (dst.index() == noreg && dst.disp() == 0) {
      if (dst.base() != tmp1) {
--- 327,58 ---
    __ addptr(tmp2, buffer);
    __ movptr(Address(tmp2, 0), card_addr);
    __ jmp(done);
  
    __ bind(runtime);
!   // Barriers might be emitted when converting between (scalarized) calling conventions for inline
!   // types. Save all argument registers before calling into the runtime.
+   __ pusha();
+   __ subptr(rsp, 64);
+   __ movdbl(Address(rsp, 0),  j_farg0);
+   __ movdbl(Address(rsp, 8),  j_farg1);
+   __ movdbl(Address(rsp, 16), j_farg2);
+   __ movdbl(Address(rsp, 24), j_farg3);
+   __ movdbl(Address(rsp, 32), j_farg4);
+   __ movdbl(Address(rsp, 40), j_farg5);
+   __ movdbl(Address(rsp, 48), j_farg6);
+   __ movdbl(Address(rsp, 56), j_farg7);
+ 
  #ifdef _LP64
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, r15_thread);
  #else
    __ push(thread);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
    __ pop(thread);
  #endif
! 
+   // Restore registers
+   __ movdbl(j_farg0, Address(rsp, 0));
+   __ movdbl(j_farg1, Address(rsp, 8));
+   __ movdbl(j_farg2, Address(rsp, 16));
+   __ movdbl(j_farg3, Address(rsp, 24));
+   __ movdbl(j_farg4, Address(rsp, 32));
+   __ movdbl(j_farg5, Address(rsp, 40));
+   __ movdbl(j_farg6, Address(rsp, 48));
+   __ movdbl(j_farg7, Address(rsp, 56));
+   __ addptr(rsp, 64);
+   __ popa();
  
    __ bind(done);
  }
  
  void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
!                                          Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
    bool in_heap = (decorators & IN_HEAP) != 0;
    bool as_normal = (decorators & AS_NORMAL) != 0;
!   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  
!   bool needs_pre_barrier = as_normal && !dest_uninitialized;
    bool needs_post_barrier = val != noreg && in_heap;
  
!   if (tmp3 == noreg) {
+     tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);
+   }
    Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
    // flatten object address if needed
    // We do it regardless of precise because we need the registers
    if (dst.index() == noreg && dst.disp() == 0) {
      if (dst.base() != tmp1) {

*** 377,21 ***
                           tmp3  /* tmp */,
                           val != noreg /* tosca_live */,
                           false /* expand_call */);
    }
    if (val == noreg) {
!     BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg);
    } else {
      Register new_val = val;
      if (needs_post_barrier) {
        // G1 barrier needs uncompressed oop for region cross check.
        if (UseCompressedOops) {
          new_val = tmp2;
          __ movptr(new_val, val);
        }
      }
!     BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg);
      if (needs_post_barrier) {
        g1_write_barrier_post(masm /*masm*/,
                              tmp1 /* store_adr */,
                              new_val /* new_val */,
                              rthread /* thread */,
--- 403,21 ---
                           tmp3  /* tmp */,
                           val != noreg /* tosca_live */,
                           false /* expand_call */);
    }
    if (val == noreg) {
!     BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg);
    } else {
      Register new_val = val;
      if (needs_post_barrier) {
        // G1 barrier needs uncompressed oop for region cross check.
        if (UseCompressedOops) {
          new_val = tmp2;
          __ movptr(new_val, val);
        }
      }
!     BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg);
      if (needs_post_barrier) {
        g1_write_barrier_post(masm /*masm*/,
                              tmp1 /* store_adr */,
                              new_val /* new_val */,
                              rthread /* thread */,
< prev index next >