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 tmp, rFlagsReg cr)
 32 %{
 33   match(Set mem (StoreP mem src));
 34   predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
 35   effect(TEMP tmp, KILL cr);
 36   ins_cost(125); // XXX
 37   format %{ "movq    $mem, $src\t# ptr" %}
 38   ins_encode %{
 39     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 40       $mem$$Address,  /* dst_narrow = */ false,
 41       $src$$Register, /* src_narrow = */ false,
 42       $tmp$$Register);
 43   %}
 44   ins_pipe(ialu_mem_reg);
 45 %}
 46 
 47 instruct storeN_shenandoah(memory mem, rRegN src, rRegP tmp, rFlagsReg cr)
 48 %{
 49   match(Set mem (StoreN mem src));
 50   predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
 51   effect(TEMP tmp, KILL cr);
 52   ins_cost(125); // XXX
 53   format %{ "movl    $mem, $src\t# ptr" %}
 54   ins_encode %{
 55     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 56       $mem$$Address,  /* dst_narrow = */ true,
 57       $src$$Register, /* src_narrow = */ true,
 58       $tmp$$Register);
 59   %}
 60   ins_pipe(ialu_mem_reg);
 61 %}
 62 
 63 instruct encodePAndStoreN_shenandoah(memory mem, any_RegP src, rRegP tmp, rFlagsReg cr)
 64 %{
 65   match(Set mem (StoreN mem (EncodeP src)));
 66   predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
 67   effect(TEMP tmp, KILL cr);
 68   ins_cost(125); // XXX
 69   format %{ "encode_heap_oop $src\n\t"
 70             "movl   $mem, $src\t# ptr" %}
 71   ins_encode %{
 72     ShenandoahBarrierSet::assembler()->store_c2(this, masm, 
 73       $mem$$Address,  /* dst_narrow = */ true,
 74       $src$$Register, /* src_narrow = */ false,
 75       $tmp$$Register);
 76   %}
 77   ins_pipe(ialu_mem_reg);
 78 %}
 79 
 80 instruct compareAndSwapP_shenandoah(rRegI res,
 81                                     indirect mem,
 82                                     rRegP tmp1, rRegP tmp2,
 83                                     rax_RegP oldval, rRegP newval,
 84                                     rFlagsReg cr)
 85 %{
 86   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
 87   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
 88   predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
 89   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr, KILL oldval);
 90 
 91   format %{ "shenandoah_cas_oop $mem,$newval" %}
 92 
 93   ins_encode %{
 94     guarantee(!UseCompressedOops, "must not be compressed oops");
 95     if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
 96       __ movptr($tmp1$$Register, $oldval$$Register);
 97       ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
 98                                                          noreg /* addr */,
 99                                                          $tmp1$$Register /* pre_val */,
100                                                          $tmp2$$Register /* tmp */);
101     }
102     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
103                                                       $res$$Register, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
104                                                       /*exchange*/ false);
105     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
106                                                        $mem$$Register /* addr */,
107                                                        $tmp1$$Register /* addr_tmp */,
108                                                        $tmp2$$Register /* tmp */);
109   %}
110   ins_pipe( pipe_cmpxchg );
111 %}
112 
113 instruct compareAndSwapN_shenandoah(rRegI res,
114                                     indirect mem,
115                                     rRegP tmp1, rRegP tmp2,
116                                     rax_RegN oldval, rRegN newval,
117                                     rFlagsReg cr) %{
118   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
119   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
120   predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
121   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr, KILL oldval);
122 
123   format %{ "shenandoah_cas_oop $mem,$newval" %}
124 
125   ins_encode %{
126     guarantee(UseCompressedOops, "must be compressed oops");
127     if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
128       __ movl($tmp1$$Register, $oldval$$Register);
129       __ decode_heap_oop($tmp1$$Register);
130       ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
131                                                          noreg /* addr */,
132                                                          $tmp1$$Register /* pre_val */,
133                                                          $tmp2$$Register /* tmp */);
134     }
135     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
136                                                       $res$$Register, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
137                                                       /*exchange*/ false);
138     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
139                                                        $mem$$Register /* addr */,
140                                                        $tmp1$$Register /* addr_tmp */,
141                                                        $tmp2$$Register /* tmp */);
142   %}
143   ins_pipe( pipe_cmpxchg );
144 %}
145 
146 instruct compareAndExchangeN_shenandoah(indirect mem,
147                                         rax_RegN oldval, rRegN newval,
148                                         rRegP tmp1, rRegP tmp2, rRegP tmp3,
149                                         rFlagsReg cr) %{
150   match(Set oldval (CompareAndExchangeN mem (Binary oldval newval)));
151   predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
152   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
153 
154   format %{ "shenandoah_cas_oop $mem,$newval" %}
155 
156   ins_encode %{
157     guarantee(UseCompressedOops, "must be compressed oops");
158     if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
159       __ movl($tmp1$$Register, $oldval$$Register);
160       __ decode_heap_oop($tmp1$$Register);
161       ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
162                                                          noreg /* addr */,
163                                                          $tmp1$$Register /* pre_val */,
164                                                          $tmp2$$Register /* tmp */);
165     }
166     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
167                                                       noreg, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
168                                                       /*exchange*/ true);
169     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
170                                                            $oldval$$Register /* obj */,
171                                                            $mem$$Register /* addr */,
172                                                            $tmp1$$Register /* tmp1 */,
173                                                            $tmp2$$Register /* tmp2 */,
174                                                            $tmp3$$Register /* tmp3 */,
175                                                            true /* narrow */);
176     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
177                                                        $mem$$Register /* addr */,
178                                                        $tmp1$$Register /* addr_tmp */,
179                                                        $tmp2$$Register /* tmp */);
180   %}
181   ins_pipe( pipe_cmpxchg );
182 %}
183 
184 instruct compareAndExchangeP_shenandoah(indirect mem,
185                                         rax_RegP oldval, rRegP newval,
186                                         rRegP tmp1, rRegP tmp2,
187                                         rFlagsReg cr)
188 %{
189   match(Set oldval (CompareAndExchangeP mem (Binary oldval newval)));
190   predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
191   effect(KILL cr, TEMP tmp1, TEMP tmp2);
192   ins_cost(1000);
193 
194   format %{ "shenandoah_cas_oop $mem,$newval" %}
195 
196   ins_encode %{
197     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
198                                                        noreg /* addr */,
199                                                        $oldval$$Register /* pre_val */,
200                                                        $tmp2$$Register /* tmp */);
201     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
202                                                       noreg, $mem$$Address, $oldval$$Register, $newval$$Register, $tmp1$$Register, $tmp2$$Register,
203                                                       /*exchange*/ true);
204     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
205                                                            $oldval$$Register /* obj */,
206                                                            $mem$$Register /* addr */,
207                                                            noreg /* tmp1 */,
208                                                            $tmp1$$Register /* tmp2 */,
209                                                            $tmp2$$Register /* tmp3 */,
210                                                            false /* narrow */);
211     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
212                                                        $mem$$Register /* addr */,
213                                                        $tmp1$$Register /* addr_tmp */,
214                                                        $tmp2$$Register /* tmp */);
215   %}
216   ins_pipe( pipe_cmpxchg );
217 %}
218 
219 instruct getAndSetP_shenandoah(indirect mem, rRegP newval, rRegP tmp1, rRegP tmp2, rFlagsReg cr)
220 %{
221   match(Set newval (GetAndSetP mem newval));
222   predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
223   effect(TEMP tmp1, TEMP tmp2, KILL cr);
224   format %{ "xchgq    $newval, $mem" %}
225   ins_encode %{
226     assert_different_registers($mem$$Register, $newval$$Register);
227     __ xchgq($newval$$Register, Address($mem$$Register, 0));
228     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
229                                                        noreg /* addr */,
230                                                        $newval$$Register /* pre_val */,
231                                                        $tmp1$$Register /* tmp */);
232     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
233                                                            $newval$$Register /* obj */,
234                                                            $mem$$Register /* addr */,
235                                                            noreg /* tmp1 */,
236                                                            $tmp1$$Register /* tmp2 */,
237                                                            $tmp2$$Register /* tmp3 */,
238                                                            false /* narrow */);
239     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
240                                                        $mem$$Register /* addr */,
241                                                        $tmp1$$Register /* addr_tmp */,
242                                                        $tmp2$$Register /* tmp */);
243   %}
244   ins_pipe(pipe_cmpxchg);
245 %}
246 
247 instruct getAndSetN_shenandoah(indirect mem, rRegN newval, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
248 %{
249   match(Set newval (GetAndSetN mem newval));
250   predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
251   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
252   format %{ "xchgq    $newval, $mem" %}
253   ins_encode %{
254     assert_different_registers($mem$$Register, $newval$$Register);
255     __ xchgl($newval$$Register, Address($mem$$Register, 0));
256     if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
257       __ movl($tmp1$$Register, $newval$$Register);
258       __ decode_heap_oop($tmp1$$Register);
259       ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
260                                                          noreg /* addr */,
261                                                          $tmp1$$Register /* pre_val */,
262                                                          $tmp2$$Register /* tmp */);
263     }
264     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
265                                                            $newval$$Register /* obj */,
266                                                            $mem$$Register /* addr */,
267                                                            $tmp1$$Register /* tmp1 */,
268                                                            $tmp2$$Register /* tmp2 */,
269                                                            $tmp3$$Register /* tmp3 */,
270                                                            true /* narrow */);
271     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
272                                                        $mem$$Register /* addr */,
273                                                        $tmp1$$Register /* addr_tmp */,
274                                                        $tmp2$$Register /* tmp */);
275   %}
276   ins_pipe(pipe_cmpxchg);
277 %}
278 
279 instruct loadP_shenandaoh(rRegP dst, memory mem, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
280 %{
281   match(Set dst (LoadP mem));
282   predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
283   effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
284   ins_cost(125); // XXX
285   format %{ "movq    $dst, $mem\t# ptr" %}
286   ins_encode %{
287     __ movq($dst$$Register, $mem$$Address);
288     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
289                                                        noreg /* addr */,
290                                                        $dst$$Register /* pre_val */,
291                                                        $tmp1$$Register /* tmp */);
292     __ lea($tmp3$$Register, $mem$$Address);
293     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
294                                                            $dst$$Register /* obj */,
295                                                            $tmp3$$Register /* addr */,
296                                                            noreg /* tmp1 */,
297                                                            $tmp1$$Register /* tmp2 */,
298                                                            $tmp2$$Register /* tmp3 */,
299                                                            false /* narrow */);
300   %}
301   ins_pipe(ialu_reg_mem); // XXX
302 %}
303 
304 instruct loadN_shenandoah(rRegN dst, indirect mem, rRegP tmp1, rRegP tmp2, rRegP tmp3, rFlagsReg cr)
305 %{
306   match(Set dst (LoadN mem));
307   predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
308   effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
309   ins_cost(125); // XXX
310   format %{ "movl    $dst, $mem\t# compressed ptr" %}
311   ins_encode %{
312     __ movl($dst$$Register, $mem$$Address);
313     if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
314       __ movl($tmp1$$Register, $dst$$Register);
315       __ decode_heap_oop($tmp1$$Register);
316       ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
317                                                          noreg /* addr */,
318                                                          $tmp1$$Register /* pre_val */,
319                                                          $tmp2$$Register /* tmp */);
320     }
321     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
322                                                            $dst$$Register /* obj */,
323                                                            $mem$$Register /* addr */,
324                                                            $tmp1$$Register /* tmp1 */,
325                                                            $tmp2$$Register /* tmp2 */,
326                                                            $tmp3$$Register /* tmp3 */,
327                                                            true /* narrow */);
328   %}
329   ins_pipe(ialu_reg_mem); // XXX
330 %}
--- EOF ---