< prev index next >

src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp

Print this page
*** 97,10 ***
--- 97,11 ---
    __ pop(saved_regs, sp);
  }
  
  static void generate_queue_test_and_insertion(MacroAssembler* masm, ByteSize index_offset, ByteSize buffer_offset, Label& runtime,
                                                const Register thread, const Register value, const Register temp1, const Register temp2) {
+   assert_different_registers(value, temp1, temp2);
    // Can we store a value in the given thread's buffer?
    // (The index field is typed as size_t.)
    __ ldr(temp1, Address(thread, in_bytes(index_offset)));   // temp1 := *(index address)
    __ cbz(temp1, runtime);                                   // jump to runtime if index == 0 (full buffer)
    // The buffer is not full, store value into it.

*** 170,11 ***
    __ cbzw(tmp1, done);
    generate_pre_barrier_slow_path(masm, obj, pre_val, thread, tmp1, tmp2, done, runtime);
  
    __ bind(runtime);
  
!   __ push_call_clobbered_registers();
  
    // Calling the runtime using the regular call_VM_leaf mechanism generates
    // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
    // that checks that the *(rfp+frame::interpreter_frame_last_sp) == nullptr.
    //
--- 171,23 ---
    __ cbzw(tmp1, done);
    generate_pre_barrier_slow_path(masm, obj, pre_val, thread, tmp1, tmp2, done, runtime);
  
    __ bind(runtime);
  
!   // save the live input values
+   RegSet saved = RegSet::of(pre_val);
+   FloatRegSet fsaved;
+ 
+   // Barriers might be emitted when converting between (scalarized) calling
+   // conventions for inline types. Save all argument registers before calling
+   // into the runtime.
+ 
+   // TODO 8366717 This came with 8284161: Implementation of Virtual Threads (Preview) later in May 2022
+   // Check if it's sufficient
+   //__ push_call_clobbered_registers();
+   assert_different_registers(rscratch1, pre_val); // push_CPU_state trashes rscratch1
+   __ push_CPU_state(true);
  
    // Calling the runtime using the regular call_VM_leaf mechanism generates
    // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
    // that checks that the *(rfp+frame::interpreter_frame_last_sp) == nullptr.
    //

*** 191,11 ***
      __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    } else {
      __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    }
  
!   __ pop_call_clobbered_registers();
  
    __ bind(done);
  
  }
  
--- 204,11 ---
      __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    } else {
      __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    }
  
!   __ pop_CPU_state(true);
  
    __ bind(done);
  
  }
  

*** 262,15 ***
    // If card is young, jump to done
    __ br(Assembler::EQ, done);
    generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, done, runtime);
  
    __ bind(runtime);
    // save the live input values
    RegSet saved = RegSet::of(store_addr);
!   __ push(saved, sp);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp1, thread);
!   __ pop(saved, sp);
  
    __ bind(done);
  }
  
  #if defined(COMPILER2)
--- 275,28 ---
    // If card is young, jump to done
    __ br(Assembler::EQ, done);
    generate_post_barrier_slow_path(masm, thread, tmp1, tmp2, done, runtime);
  
    __ bind(runtime);
+ 
    // save the live input values
    RegSet saved = RegSet::of(store_addr);
!   FloatRegSet fsaved;
+ 
+   // Barriers might be emitted when converting between (scalarized) calling
+   // conventions for inline types. Save all argument registers before calling
+   // into the runtime.
+   // TODO 8366717 Without this, r11 is corrupted below and it holds the array of pre-allocated value objects in the C2I adapter...
+   // Check if__ push_call_clobbered_registers() is sufficient
+   assert_different_registers(rscratch1, tmp1); // push_CPU_state trashes rscratch1
+   __ enter();
+   __ push_CPU_state(true);
+ 
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp1, thread);
! 
+   __ pop_CPU_state(true);
+   __ leave();
  
    __ bind(done);
  }
  
  #if defined(COMPILER2)

*** 389,44 ***
    }
  }
  
  void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                           Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
    // flatten object address if needed
    if (dst.index() == noreg && dst.offset() == 0) {
      if (dst.base() != tmp3) {
        __ mov(tmp3, dst.base());
      }
    } else {
      __ lea(tmp3, dst);
    }
  
!   g1_write_barrier_pre(masm,
!                        tmp3 /* obj */,
!                        tmp2 /* pre_val */,
!                        rthread /* thread */,
!                        tmp1  /* tmp1 */,
!                        rscratch2  /* tmp2 */,
!                        val != noreg /* tosca_live */,
!                        false /* expand_call */);
  
    if (val == noreg) {
      BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), noreg, noreg, noreg, noreg);
    } else {
      // G1 barrier needs uncompressed oop for region cross check.
      Register new_val = val;
!     if (UseCompressedOops) {
!       new_val = rscratch2;
!       __ mov(new_val, val);
      }
      BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), val, noreg, noreg, noreg);
!     g1_write_barrier_post(masm,
!                           tmp3 /* store_adr */,
!                           new_val /* new_val */,
!                           rthread /* thread */,
!                           tmp1 /* tmp1 */,
!                           tmp2 /* tmp2 */);
    }
  
  }
  
  #ifdef COMPILER1
--- 415,61 ---
    }
  }
  
  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);
+ 
+   assert_different_registers(val, tmp1, tmp2, tmp3);
+ 
    // flatten object address if needed
    if (dst.index() == noreg && dst.offset() == 0) {
      if (dst.base() != tmp3) {
        __ mov(tmp3, dst.base());
      }
    } else {
      __ lea(tmp3, dst);
    }
  
!   if (needs_pre_barrier) {
!     g1_write_barrier_pre(masm,
!                          tmp3 /* obj */,
!                          tmp2 /* pre_val */,
!                          rthread /* thread */,
!                          tmp1  /* tmp1 */,
!                          rscratch2  /* tmp2 */,
!                          val != noreg /* tosca_live */,
+                          false /* expand_call */);
+   }
  
    if (val == noreg) {
      BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), noreg, noreg, noreg, noreg);
    } else {
      // G1 barrier needs uncompressed oop for region cross check.
      Register new_val = val;
!     if (needs_post_barrier) {
!       if (UseCompressedOops) {
!         new_val = rscratch2;
+         __ mov(new_val, val);
+       }
      }
+ 
      BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), val, noreg, noreg, noreg);
!     if (needs_post_barrier) {
!       g1_write_barrier_post(masm,
!                             tmp3 /* store_adr */,
!                             new_val /* new_val */,
!                             rthread /* thread */,
!                             tmp1 /* tmp1 */,
+                             tmp2 /* tmp2 */);
+     }
    }
  
  }
  
  #ifdef COMPILER1
< prev index next >