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 %}