diff a/src/hotspot/cpu/riscv/gc/g1/g1_riscv.ad b/src/hotspot/cpu/riscv/gc/g1/g1_riscv.ad --- a/src/hotspot/cpu/riscv/gc/g1/g1_riscv.ad +++ b/src/hotspot/cpu/riscv/gc/g1/g1_riscv.ad @@ -1,7 +1,7 @@ // -// Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2024, Huawei Technologies Co., Ltd. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License version 2 only, as @@ -72,10 +72,130 @@ g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, xthread, tmp1, tmp2, new_val_may_be_null); } %} + +// TODO 8350865 (same applies to g1StoreLSpecialTwoOops) +// - Do not set/overwrite barrier data here, also handle G1C2BarrierPostNotNull + +instruct g1StoreLSpecialOneOopOff0(indirect mem, iRegLNoSp src, immI0 off, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr) +%{ + predicate(UseG1GC); + match(Set mem (StoreLSpecial mem (Binary src off))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr); + ins_cost(STORE_COST); + format %{ "sd $src, $mem\t# g1StoreLSpecialOneOopOff0" %} + ins_encode %{ + guarantee($mem$$disp == 0, "impossible encoding"); + ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost); + + write_barrier_pre(masm, this, + $mem$$Register /* obj */, + $tmp1$$Register /* pre_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */, + RegSet::of($mem$$Register, $src$$Register) /* preserve */); + + __ sd($src$$Register, Address($mem$$Register)); + + // Extract the narrow oop field value + __ zext($tmp1$$Register, $src$$Register, 32); + __ decode_heap_oop($tmp1$$Register, $tmp1$$Register); + write_barrier_post(masm, this, + $mem$$Register /* store_addr */, + $tmp1$$Register /* new_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */); + %} + ins_pipe(istore_reg_mem); +%} + +instruct g1StoreLSpecialOneOopOff4(indirect mem, iRegLNoSp src, immI_4 off, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4, rFlagsReg cr) +%{ + predicate(UseG1GC); + match(Set mem (StoreLSpecial mem (Binary src off))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + ins_cost(STORE_COST); + format %{ "sd $src, $mem\t# g1StoreLSpecialOneOopOff4" %} + ins_encode %{ + guarantee($mem$$disp == 0, "impossible encoding"); + ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost); + + // Adjust address to point to narrow oop + __ add($tmp4$$Register, $mem$$Register, 4); + write_barrier_pre(masm, this, + $tmp4$$Register /* obj */, + $tmp1$$Register /* pre_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */, + RegSet::of($mem$$Register, $src$$Register, $tmp4$$Register) /* preserve */); + + __ sd($src$$Register, Address($mem$$Register)); + + // Shift long value to extract the narrow oop field value and zero-extend it + __ srli($tmp1$$Register, $src$$Register, 32); + __ decode_heap_oop($tmp1$$Register, $tmp1$$Register); + write_barrier_post(masm, this, + $tmp4$$Register /* store_addr */, + $tmp1$$Register /* new_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */); + %} + ins_pipe(istore_reg_mem); +%} + +instruct g1StoreLSpecialTwoOops(indirect mem, iRegLNoSp src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4, rFlagsReg cr) +%{ + predicate(UseG1GC); + match(Set mem (StoreLSpecial mem src)); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + ins_cost(STORE_COST); + format %{ "sd $src, $mem\t# g1StoreLSpecialTwoOops" %} + ins_encode %{ + guarantee($mem$$disp == 0, "impossible encoding"); + ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost); + + write_barrier_pre(masm, this, + $mem$$Register /* obj */, + $tmp1$$Register /* pre_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */, + RegSet::of($mem$$Register, $src$$Register) /* preserve */); + // Adjust address to point to the second narrow oop in the long value + __ add($tmp4$$Register, $mem$$Register, 4); + write_barrier_pre(masm, this, + $tmp4$$Register /* obj */, + $tmp1$$Register /* pre_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */, + RegSet::of($mem$$Register, $src$$Register, $tmp4$$Register) /* preserve */); + + __ sd($src$$Register, Address($mem$$Register)); + + // Zero-extend first narrow oop to long + __ zext($tmp1$$Register, $src$$Register, 32); + __ decode_heap_oop($tmp1$$Register, $tmp1$$Register); + write_barrier_post(masm, this, + $mem$$Register /* store_addr */, + $tmp1$$Register /* new_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */); + + // Shift long value to extract the second narrow oop field value + __ srli($tmp1$$Register, $src$$Register, 32); + __ decode_heap_oop($tmp1$$Register, $tmp1$$Register); + write_barrier_post(masm, this, + $tmp4$$Register /* store_addr */, + $tmp1$$Register /* new_val */, + $tmp2$$Register /* tmp1 */, + $tmp3$$Register /* tmp2 */); + %} + ins_pipe(istore_reg_mem); +%} + + instruct g1StoreP(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr) %{ predicate(UseG1GC && n->as_Store()->barrier_data() != 0); match(Set mem (StoreP mem src)); effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);