1 //
2 // Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
3 // Copyright (c) 2024, Huawei Technologies Co., Ltd. All rights reserved.
4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 //
6 // This code is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License version 2 only, as
8 // published by the Free Software Foundation.
9 //
10 // This code is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // version 2 for more details (a copy is included in the LICENSE file that
14 // accompanied this code).
15 //
16 // You should have received a copy of the GNU General Public License version
17 // 2 along with this work; if not, write to the Free Software Foundation,
18 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 // or visit www.oracle.com if you need additional information or have any
22 // questions.
57 g1_asm->g1_write_barrier_pre_c2(masm, obj, pre_val, xthread, tmp1, tmp2, stub);
58 }
59
60 static void write_barrier_post(MacroAssembler* masm,
61 const MachNode* node,
62 Register store_addr,
63 Register new_val,
64 Register tmp1,
65 Register tmp2) {
66 if (!G1BarrierStubC2::needs_post_barrier(node)) {
67 return;
68 }
69 Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
70 G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
71 bool new_val_may_be_null = G1BarrierStubC2::post_new_val_may_be_null(node);
72 g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, xthread, tmp1, tmp2, new_val_may_be_null);
73 }
74
75 %}
76
77 instruct g1StoreP(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
78 %{
79 predicate(UseG1GC && n->as_Store()->barrier_data() != 0);
80 match(Set mem (StoreP mem src));
81 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
82 ins_cost(STORE_COST);
83 format %{ "sd $src, $mem\t# ptr" %}
84 ins_encode %{
85 guarantee($mem$$disp == 0, "impossible encoding");
86 write_barrier_pre(masm, this,
87 $mem$$Register /* obj */,
88 $tmp1$$Register /* pre_val */,
89 $tmp2$$Register /* tmp1 */,
90 $tmp3$$Register /* tmp2 */,
91 RegSet::of($mem$$Register, $src$$Register) /* preserve */);
92 __ sd($src$$Register, Address($mem$$Register));
93 write_barrier_post(masm, this,
94 $mem$$Register /* store_addr */,
95 $src$$Register /* new_val */,
96 $tmp2$$Register /* tmp1 */,
|
1 //
2 // Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
3 // Copyright (c) 2024, Huawei Technologies Co., Ltd. All rights reserved.
4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 //
6 // This code is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License version 2 only, as
8 // published by the Free Software Foundation.
9 //
10 // This code is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // version 2 for more details (a copy is included in the LICENSE file that
14 // accompanied this code).
15 //
16 // You should have received a copy of the GNU General Public License version
17 // 2 along with this work; if not, write to the Free Software Foundation,
18 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 // or visit www.oracle.com if you need additional information or have any
22 // questions.
57 g1_asm->g1_write_barrier_pre_c2(masm, obj, pre_val, xthread, tmp1, tmp2, stub);
58 }
59
60 static void write_barrier_post(MacroAssembler* masm,
61 const MachNode* node,
62 Register store_addr,
63 Register new_val,
64 Register tmp1,
65 Register tmp2) {
66 if (!G1BarrierStubC2::needs_post_barrier(node)) {
67 return;
68 }
69 Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
70 G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
71 bool new_val_may_be_null = G1BarrierStubC2::post_new_val_may_be_null(node);
72 g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, xthread, tmp1, tmp2, new_val_may_be_null);
73 }
74
75 %}
76
77
78 // TODO 8350865 (same applies to g1StoreLSpecialTwoOops)
79 // - Do not set/overwrite barrier data here, also handle G1C2BarrierPostNotNull
80
81 instruct g1StoreLSpecialOneOopOff0(indirect mem, iRegLNoSp src, immI0 off, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
82 %{
83 predicate(UseG1GC);
84 match(Set mem (StoreLSpecial mem (Binary src off)));
85 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
86 ins_cost(STORE_COST);
87 format %{ "sd $src, $mem\t# g1StoreLSpecialOneOopOff0" %}
88 ins_encode %{
89 guarantee($mem$$disp == 0, "impossible encoding");
90 ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost);
91
92 write_barrier_pre(masm, this,
93 $mem$$Register /* obj */,
94 $tmp1$$Register /* pre_val */,
95 $tmp2$$Register /* tmp1 */,
96 $tmp3$$Register /* tmp2 */,
97 RegSet::of($mem$$Register, $src$$Register) /* preserve */);
98
99 __ sd($src$$Register, Address($mem$$Register));
100
101 // Extract the narrow oop field value
102 __ zext($tmp1$$Register, $src$$Register, 32);
103 __ decode_heap_oop($tmp1$$Register, $tmp1$$Register);
104 write_barrier_post(masm, this,
105 $mem$$Register /* store_addr */,
106 $tmp1$$Register /* new_val */,
107 $tmp2$$Register /* tmp1 */,
108 $tmp3$$Register /* tmp2 */);
109 %}
110 ins_pipe(istore_reg_mem);
111 %}
112
113 instruct g1StoreLSpecialOneOopOff4(indirect mem, iRegLNoSp src, immI_4 off, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4, rFlagsReg cr)
114 %{
115 predicate(UseG1GC);
116 match(Set mem (StoreLSpecial mem (Binary src off)));
117 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
118 ins_cost(STORE_COST);
119 format %{ "sd $src, $mem\t# g1StoreLSpecialOneOopOff4" %}
120 ins_encode %{
121 guarantee($mem$$disp == 0, "impossible encoding");
122 ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost);
123
124 // Adjust address to point to narrow oop
125 __ add($tmp4$$Register, $mem$$Register, 4);
126 write_barrier_pre(masm, this,
127 $tmp4$$Register /* obj */,
128 $tmp1$$Register /* pre_val */,
129 $tmp2$$Register /* tmp1 */,
130 $tmp3$$Register /* tmp2 */,
131 RegSet::of($mem$$Register, $src$$Register, $tmp4$$Register) /* preserve */);
132
133 __ sd($src$$Register, Address($mem$$Register));
134
135 // Shift long value to extract the narrow oop field value and zero-extend it
136 __ srli($tmp1$$Register, $src$$Register, 32);
137 __ decode_heap_oop($tmp1$$Register, $tmp1$$Register);
138 write_barrier_post(masm, this,
139 $tmp4$$Register /* store_addr */,
140 $tmp1$$Register /* new_val */,
141 $tmp2$$Register /* tmp1 */,
142 $tmp3$$Register /* tmp2 */);
143 %}
144 ins_pipe(istore_reg_mem);
145 %}
146
147 instruct g1StoreLSpecialTwoOops(indirect mem, iRegLNoSp src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4, rFlagsReg cr)
148 %{
149 predicate(UseG1GC);
150 match(Set mem (StoreLSpecial mem src));
151 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
152 ins_cost(STORE_COST);
153 format %{ "sd $src, $mem\t# g1StoreLSpecialTwoOops" %}
154 ins_encode %{
155 guarantee($mem$$disp == 0, "impossible encoding");
156 ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost);
157
158 write_barrier_pre(masm, this,
159 $mem$$Register /* obj */,
160 $tmp1$$Register /* pre_val */,
161 $tmp2$$Register /* tmp1 */,
162 $tmp3$$Register /* tmp2 */,
163 RegSet::of($mem$$Register, $src$$Register) /* preserve */);
164 // Adjust address to point to the second narrow oop in the long value
165 __ add($tmp4$$Register, $mem$$Register, 4);
166 write_barrier_pre(masm, this,
167 $tmp4$$Register /* obj */,
168 $tmp1$$Register /* pre_val */,
169 $tmp2$$Register /* tmp1 */,
170 $tmp3$$Register /* tmp2 */,
171 RegSet::of($mem$$Register, $src$$Register, $tmp4$$Register) /* preserve */);
172
173 __ sd($src$$Register, Address($mem$$Register));
174
175 // Zero-extend first narrow oop to long
176 __ zext($tmp1$$Register, $src$$Register, 32);
177 __ decode_heap_oop($tmp1$$Register, $tmp1$$Register);
178 write_barrier_post(masm, this,
179 $mem$$Register /* store_addr */,
180 $tmp1$$Register /* new_val */,
181 $tmp2$$Register /* tmp1 */,
182 $tmp3$$Register /* tmp2 */);
183
184 // Shift long value to extract the second narrow oop field value
185 __ srli($tmp1$$Register, $src$$Register, 32);
186 __ decode_heap_oop($tmp1$$Register, $tmp1$$Register);
187 write_barrier_post(masm, this,
188 $tmp4$$Register /* store_addr */,
189 $tmp1$$Register /* new_val */,
190 $tmp2$$Register /* tmp1 */,
191 $tmp3$$Register /* tmp2 */);
192 %}
193 ins_pipe(istore_reg_mem);
194 %}
195
196
197 instruct g1StoreP(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
198 %{
199 predicate(UseG1GC && n->as_Store()->barrier_data() != 0);
200 match(Set mem (StoreP mem src));
201 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
202 ins_cost(STORE_COST);
203 format %{ "sd $src, $mem\t# ptr" %}
204 ins_encode %{
205 guarantee($mem$$disp == 0, "impossible encoding");
206 write_barrier_pre(masm, this,
207 $mem$$Register /* obj */,
208 $tmp1$$Register /* pre_val */,
209 $tmp2$$Register /* tmp1 */,
210 $tmp3$$Register /* tmp2 */,
211 RegSet::of($mem$$Register, $src$$Register) /* preserve */);
212 __ sd($src$$Register, Address($mem$$Register));
213 write_barrier_post(masm, this,
214 $mem$$Register /* store_addr */,
215 $src$$Register /* new_val */,
216 $tmp2$$Register /* tmp1 */,
|