*** 130,10 *** --- 130,11 --- __ bind(done); } 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.
*** 203,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. // --- 204,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. //
*** 224,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); } --- 237,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); }
*** 365,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 --- 378,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