1 //
2 // Copyright (c) 2018, Red Hat, Inc. All rights reserved.
3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 //
5 // This code is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License version 2 only, as
7 // published by the Free Software Foundation.
8 //
9 // This code is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 // version 2 for more details (a copy is included in the LICENSE file that
13 // accompanied this code).
14 //
15 // You should have received a copy of the GNU General Public License version
16 // 2 along with this work; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 // or visit www.oracle.com if you need additional information or have any
21 // questions.
22 //
23 //
24
25 source %{
26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
27 #include "gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp"
28 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
29 %}
30
31 instruct storeP_shenandoah(memory mem, any_RegP src, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
32 %{
33 match(Set mem (StoreP mem src));
34 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
35 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
36 ins_cost(125); // XXX
37 format %{ "movq $mem, $src\t# ptr" %}
38 ins_encode %{
39 __ lea($tmp1$$Register, $mem$$Address);
40 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
41 $tmp1$$Register /* addr */,
42 $tmp2$$Register /* pre_val */,
43 $tmp3$$Register /* tmp */);
44 __ movq(Address($tmp1$$Register, 0), $src$$Register);
45 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
46 noreg /* addr */,
47 $tmp1$$Register /* addr_tmp */,
48 $tmp2$$Register /* tmp */);
49 %}
50 ins_pipe(ialu_mem_reg);
51 %}
52
53 instruct storeN_shenandoah(memory mem, rRegN src, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
54 %{
55 match(Set mem (StoreN mem src));
56 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
57 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
58 ins_cost(125); // XXX
59 format %{ "movl $mem, $src\t# ptr" %}
60 ins_encode %{
61 __ lea($tmp1$$Register, $mem$$Address);
62 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
63 $tmp1$$Register /* addr */,
64 $tmp2$$Register /* pre_val */,
65 $tmp3$$Register /* tmp */);
66 __ movl(Address($tmp1$$Register, 0), $src$$Register);
67 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
68 noreg /* addr */,
69 $tmp1$$Register /* addr_tmp */,
70 $tmp2$$Register /* tmp */);
71 %}
72 ins_pipe(ialu_mem_reg);
73 %}
74
75 instruct encodePAndStoreN_shenandoah(memory mem, any_RegP src, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
76 %{
77 match(Set mem (StoreN mem (EncodeP src)));
78 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
79 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
80 ins_cost(125); // XXX
81 format %{ "encode_heap_oop $src\n\t"
82 "movl $mem, $src\t# ptr" %}
83 ins_encode %{
84 __ lea($tmp1$$Register, $mem$$Address);
85 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
86 $tmp1$$Register /* addr */,
87 $tmp2$$Register /* pre_val */,
88 $tmp3$$Register /* tmp */);
89 __ movq($tmp3$$Register, $src$$Register);
90 if ((barrier_data() & ShenandoahBarrierCardMarkNotNull) == 0) {
91 __ encode_heap_oop($tmp3$$Register);
92 } else {
93 __ encode_heap_oop_not_null($tmp3$$Register);
94 }
95 __ movl(Address($tmp1$$Register, 0), $tmp3$$Register);
96 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
97 noreg /* addr */,
98 $tmp1$$Register /* addr_tmp */,
99 $tmp2$$Register /* tmp */);
100 %}
101 ins_pipe(ialu_mem_reg);
102 %}
103
104 instruct compareAndSwapP_shenandoah(rRegI res,
105 indirect mem,
106 rRegP tmp1, rRegP tmp2,
107 rax_RegP oldval, rRegP newval,
108 rFlagsReg cr)
109 %{
110 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
111 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
112 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
113 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr, KILL oldval);
114
115 format %{ "shenandoah_cas_oop $mem,$newval" %}
116
117 ins_encode %{
118 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
119 noreg /* addr */,
120 $oldval$$Register /* pre_val */,
121 $tmp2$$Register /* tmp */);
122 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
123 $res$$Register, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
124 /*exchange*/ false);
125 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
126 $mem$$Register /* addr */,
127 $tmp1$$Register /* addr_tmp */,
128 $tmp2$$Register /* tmp */);
129 %}
130 ins_pipe( pipe_cmpxchg );
131 %}
132
133 instruct compareAndSwapN_shenandoah(rRegI res,
134 indirect mem,
135 rRegP tmp1, rRegP tmp2,
136 rax_RegN oldval, rRegN newval,
137 rFlagsReg cr) %{
138 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
139 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
140 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
141 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr, KILL oldval);
142
143 format %{ "shenandoah_cas_oop $mem,$newval" %}
144
145 ins_encode %{
146 guarantee(UseCompressedOops, "must be compressed oops");
147 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
148 __ movl($tmp1$$Register, $oldval$$Register);
149 __ decode_heap_oop($tmp1$$Register);
150 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
151 noreg /* addr */,
152 $tmp1$$Register /* pre_val */,
153 $tmp2$$Register /* tmp */);
154 }
155 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
156 $res$$Register, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
157 /*exchange*/ false);
158 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
159 $mem$$Register /* addr */,
160 $tmp1$$Register /* addr_tmp */,
161 $tmp2$$Register /* tmp */);
162 %}
163 ins_pipe( pipe_cmpxchg );
164 %}
165
166 instruct compareAndExchangeN_shenandoah(indirect mem,
167 rax_RegN oldval, rRegN newval,
168 rRegP tmp1, rRegP tmp2, rRegP tmp3,
169 rFlagsReg cr) %{
170 match(Set oldval (CompareAndExchangeN mem (Binary oldval newval)));
171 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
172 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
173
174 format %{ "shenandoah_cas_oop $mem,$newval" %}
175
176 ins_encode %{
177 guarantee(UseCompressedOops, "must be compressed oops");
178 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
179 __ movl($tmp1$$Register, $oldval$$Register);
180 __ decode_heap_oop($tmp1$$Register);
181 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
182 noreg /* addr */,
183 $tmp1$$Register /* pre_val */,
184 $tmp2$$Register /* tmp */);
185 }
186 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
187 noreg, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
188 /*exchange*/ true);
189 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
190 $oldval$$Register /* obj */,
191 $mem$$Register /* addr */,
192 $tmp1$$Register /* tmp1 */,
193 $tmp2$$Register /* tmp2 */,
194 $tmp3$$Register /* tmp3 */,
195 true /* narrow */);
196 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
197 $mem$$Register /* addr */,
198 $tmp1$$Register /* addr_tmp */,
199 $tmp2$$Register /* tmp */);
200 %}
201 ins_pipe( pipe_cmpxchg );
202 %}
203
204 instruct compareAndExchangeP_shenandoah(indirect mem,
205 rax_RegP oldval, rRegP newval,
206 rRegP tmp1, rRegP tmp2,
207 rFlagsReg cr)
208 %{
209 match(Set oldval (CompareAndExchangeP mem (Binary oldval newval)));
210 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
211 effect(KILL cr, TEMP tmp1, TEMP tmp2);
212 ins_cost(1000);
213
214 format %{ "shenandoah_cas_oop $mem,$newval" %}
215
216 ins_encode %{
217 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
218 noreg /* addr */,
219 $oldval$$Register /* pre_val */,
220 $tmp2$$Register /* tmp */);
221 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
222 noreg, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
223 /*exchange*/ true);
224 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
225 $oldval$$Register /* obj */,
226 $mem$$Register /* addr */,
227 noreg /* tmp1 */,
228 $tmp1$$Register /* tmp2 */,
229 $tmp2$$Register /* tmp3 */,
230 false /* narrow */);
231 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
232 $mem$$Register /* addr */,
233 $tmp1$$Register /* addr_tmp */,
234 $tmp2$$Register /* tmp */);
235 %}
236 ins_pipe( pipe_cmpxchg );
237 %}
238
239 instruct getAndSetP_shenandoah(indirect mem, rRegP newval, rRegP tmp1, rRegP tmp2, rFlagsReg cr)
240 %{
241 match(Set newval (GetAndSetP mem newval));
242 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
243 effect(TEMP tmp1, TEMP tmp2, KILL cr);
244 format %{ "xchgq $newval, $mem" %}
245 ins_encode %{
246 assert_different_registers($mem$$Register, $newval$$Register);
247 __ xchgq($newval$$Register, Address($mem$$Register, 0));
248 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
249 noreg /* addr */,
250 $newval$$Register /* pre_val */,
251 $tmp1$$Register /* tmp */);
252 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
253 $newval$$Register /* obj */,
254 $mem$$Register /* addr */,
255 noreg /* tmp1 */,
256 $tmp1$$Register /* tmp2 */,
257 $tmp2$$Register /* tmp3 */,
258 false /* narrow */);
259 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
260 $mem$$Register /* addr */,
261 $tmp1$$Register /* addr_tmp */,
262 $tmp2$$Register /* tmp */);
263 %}
264 ins_pipe(pipe_cmpxchg);
265 %}
266
267 instruct getAndSetN_shenandoah(indirect mem, rRegN newval, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
268 %{
269 match(Set newval (GetAndSetN mem newval));
270 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
271 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
272 format %{ "xchgq $newval, $mem" %}
273 ins_encode %{
274 assert_different_registers($mem$$Register, $newval$$Register);
275 __ xchgl($newval$$Register, Address($mem$$Register, 0));
276 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
277 __ movl($tmp1$$Register, $newval$$Register);
278 __ decode_heap_oop($tmp1$$Register);
279 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
280 noreg /* addr */,
281 $tmp1$$Register /* pre_val */,
282 $tmp2$$Register /* tmp */);
283 }
284 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
285 $newval$$Register /* obj */,
286 $mem$$Register /* addr */,
287 $tmp1$$Register /* tmp1 */,
288 $tmp2$$Register /* tmp2 */,
289 $tmp3$$Register /* tmp3 */,
290 true /* narrow */);
291 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
292 $mem$$Register /* addr */,
293 $tmp1$$Register /* addr_tmp */,
294 $tmp2$$Register /* tmp */);
295 %}
296 ins_pipe(pipe_cmpxchg);
297 %}
298
299 instruct loadP_shenandaoh(rRegP dst, memory mem, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
300 %{
301 match(Set dst (LoadP mem));
302 predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
303 effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
304 ins_cost(125); // XXX
305 format %{ "movq $dst, $mem\t# ptr" %}
306 ins_encode %{
307 __ movq($dst$$Register, $mem$$Address);
308 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
309 noreg /* addr */,
310 $dst$$Register /* pre_val */,
311 $tmp1$$Register /* tmp */);
312 __ lea($tmp3$$Register, $mem$$Address);
313 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
314 $dst$$Register /* obj */,
315 $tmp3$$Register /* addr */,
316 noreg /* tmp1 */,
317 $tmp1$$Register /* tmp2 */,
318 $tmp2$$Register /* tmp3 */,
319 false /* narrow */);
320 %}
321 ins_pipe(ialu_reg_mem); // XXX
322 %}
323
324 instruct loadN_shenandoah(rRegN dst, indirect mem, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
325 %{
326 match(Set dst (LoadN mem));
327 predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
328 effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
329 ins_cost(125); // XXX
330 format %{ "movl $dst, $mem\t# compressed ptr" %}
331 ins_encode %{
332 __ movl($dst$$Register, $mem$$Address);
333 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
334 __ movl($tmp1$$Register, $dst$$Register);
335 __ decode_heap_oop($tmp1$$Register);
336 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
337 noreg /* addr */,
338 $tmp1$$Register /* pre_val */,
339 $tmp2$$Register /* tmp */);
340 }
341 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
342 $dst$$Register /* obj */,
343 $mem$$Register /* addr */,
344 $tmp1$$Register /* tmp1 */,
345 $tmp2$$Register /* tmp2 */,
346 $tmp3$$Register /* tmp3 */,
347 true /* narrow */);
348 %}
349 ins_pipe(ialu_reg_mem); // XXX
350 %}