< prev index next > src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp
Print this page
__ 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.
__ 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.
//
__ 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.
//
__ 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);
}
__ 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);
}
// 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)
// 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)
}
}
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
}
}
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 >