1 /*
2 * Copyright (c) 2018, Oracle and/or its affiliates. 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 #include "precompiled.hpp"
26 #include "asm/macroAssembler.inline.hpp"
27 #include "gc/g1/g1BarrierSet.hpp"
28 #include "gc/g1/g1BarrierSetAssembler.hpp"
29 #include "gc/g1/g1BarrierSetRuntime.hpp"
30 #include "gc/g1/g1CardTable.hpp"
31 #include "gc/g1/g1SATBMarkQueueSet.hpp"
32 #include "gc/g1/g1ThreadLocalData.hpp"
33 #include "gc/g1/heapRegion.hpp"
34 #include "interpreter/interp_masm.hpp"
35 #include "runtime/sharedRuntime.hpp"
36 #include "utilities/macros.hpp"
37 #ifdef COMPILER1
38 #include "c1/c1_LIRAssembler.hpp"
39 #include "c1/c1_MacroAssembler.hpp"
40 #include "gc/g1/c1/g1BarrierSetC1.hpp"
41 #endif
42
43 #define __ masm->
44
45 void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
46 Register addr, Register count) {
47 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
48 // With G1, don't generate the call if we statically know that the target in uninitialized
49 if (!dest_uninitialized) {
50 Register tmp = O5;
298
299 __ bind(young_card);
300 // We didn't take the branch, so we're already dirty: return.
301 // Use return-from-leaf
302 __ retl();
303 __ delayed()->nop();
304
305 // Not dirty.
306 __ bind(not_already_dirty);
307
308 // Get O0 + O1 into a reg by itself
309 __ add(O0, O1, O3);
310
311 // First, dirty it.
312 __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty).
313
314 int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
315 int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
316 __ bind(restart);
317
318 // Load the index into the update buffer. DirtyCardQueue::_index is
319 // a size_t so ld_ptr is appropriate here.
320 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0);
321
322 // index == 0?
323 __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
324
325 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1);
326 __ sub(L0, oopSize, L0);
327
328 __ st_ptr(O3, L1, L0); // [_buf + index] := I0
329 // Use return-from-leaf
330 __ retl();
331 __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset);
332
333 __ bind(refill);
334 address handle_zero =
335 CAST_FROM_FN_PTR(address,
336 &DirtyCardQueueSet::handle_zero_index_for_thread);
337 // This should be rare enough that we can afford to save all the
338 // scratch registers that the calling context might be using.
339 __ mov(G1_scratch, L3);
340 __ mov(G3_scratch, L5);
341 // We need the value of O3 above (for the write into the buffer), so we
342 // save and restore it.
343 __ mov(O3, L6);
344 // Since the call will overwrite O7, we save and restore that, as well.
345 __ mov(O7, L4);
346
347 __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread);
348 __ mov(L3, G1_scratch);
349 __ mov(L5, G3_scratch);
350 __ mov(L6, O3);
351 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
352 __ delayed()->mov(L4, O7);
353
354 dirty_card_log_enqueue = start;
355 dirty_card_log_enqueue_end = __ pc();
356 // XXX Should have a guarantee here about not going off the end!
656 // Not dirty.
657 __ bind(not_already_dirty);
658
659 // Get cardtable + tmp into a reg by itself
660 __ add(addr, cardtable, tmp2);
661
662 // First, dirty it.
663 __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty).
664
665 Register tmp3 = cardtable;
666 Register tmp4 = tmp;
667
668 // these registers are now dead
669 addr = cardtable = tmp = noreg;
670
671 int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
672 int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
673
674 __ bind(restart);
675
676 // Get the index into the update buffer. DirtyCardQueue::_index is
677 // a size_t so ld_ptr is appropriate here.
678 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3);
679
680 // index == 0?
681 __ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill);
682
683 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4);
684 __ sub(tmp3, oopSize, tmp3);
685
686 __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card>
687 // Use return-from-leaf
688 __ retl();
689 __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset);
690
691 __ bind(refill);
692
693 __ save_live_registers_no_oop_map(true);
694
695 __ call_VM_leaf(L7_thread_cache,
696 CAST_FROM_FN_PTR(address,
697 DirtyCardQueueSet::handle_zero_index_for_thread),
698 G2_thread);
699
700 __ restore_live_registers(true);
701
702 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
703 __ epilogue();
704 }
705
706 #undef __
707
708 #endif // COMPILER1
|
1 /*
2 * Copyright (c) 2019, Oracle and/or its affiliates. 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 #include "precompiled.hpp"
26 #include "asm/macroAssembler.inline.hpp"
27 #include "gc/g1/g1BarrierSet.hpp"
28 #include "gc/g1/g1BarrierSetAssembler.hpp"
29 #include "gc/g1/g1BarrierSetRuntime.hpp"
30 #include "gc/g1/g1CardTable.hpp"
31 #include "gc/g1/g1DirtyCardQueue.hpp"
32 #include "gc/g1/g1SATBMarkQueueSet.hpp"
33 #include "gc/g1/g1ThreadLocalData.hpp"
34 #include "gc/g1/heapRegion.hpp"
35 #include "interpreter/interp_masm.hpp"
36 #include "runtime/sharedRuntime.hpp"
37 #include "utilities/macros.hpp"
38 #ifdef COMPILER1
39 #include "c1/c1_LIRAssembler.hpp"
40 #include "c1/c1_MacroAssembler.hpp"
41 #include "gc/g1/c1/g1BarrierSetC1.hpp"
42 #endif
43
44 #define __ masm->
45
46 void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
47 Register addr, Register count) {
48 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
49 // With G1, don't generate the call if we statically know that the target in uninitialized
50 if (!dest_uninitialized) {
51 Register tmp = O5;
299
300 __ bind(young_card);
301 // We didn't take the branch, so we're already dirty: return.
302 // Use return-from-leaf
303 __ retl();
304 __ delayed()->nop();
305
306 // Not dirty.
307 __ bind(not_already_dirty);
308
309 // Get O0 + O1 into a reg by itself
310 __ add(O0, O1, O3);
311
312 // First, dirty it.
313 __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty).
314
315 int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
316 int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
317 __ bind(restart);
318
319 // Load the index into the update buffer. G1DirtyCardQueue::_index is
320 // a size_t so ld_ptr is appropriate here.
321 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0);
322
323 // index == 0?
324 __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
325
326 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1);
327 __ sub(L0, oopSize, L0);
328
329 __ st_ptr(O3, L1, L0); // [_buf + index] := I0
330 // Use return-from-leaf
331 __ retl();
332 __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset);
333
334 __ bind(refill);
335 address handle_zero =
336 CAST_FROM_FN_PTR(address,
337 &G1DirtyCardQueueSet::handle_zero_index_for_thread);
338 // This should be rare enough that we can afford to save all the
339 // scratch registers that the calling context might be using.
340 __ mov(G1_scratch, L3);
341 __ mov(G3_scratch, L5);
342 // We need the value of O3 above (for the write into the buffer), so we
343 // save and restore it.
344 __ mov(O3, L6);
345 // Since the call will overwrite O7, we save and restore that, as well.
346 __ mov(O7, L4);
347
348 __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread);
349 __ mov(L3, G1_scratch);
350 __ mov(L5, G3_scratch);
351 __ mov(L6, O3);
352 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
353 __ delayed()->mov(L4, O7);
354
355 dirty_card_log_enqueue = start;
356 dirty_card_log_enqueue_end = __ pc();
357 // XXX Should have a guarantee here about not going off the end!
657 // Not dirty.
658 __ bind(not_already_dirty);
659
660 // Get cardtable + tmp into a reg by itself
661 __ add(addr, cardtable, tmp2);
662
663 // First, dirty it.
664 __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty).
665
666 Register tmp3 = cardtable;
667 Register tmp4 = tmp;
668
669 // these registers are now dead
670 addr = cardtable = tmp = noreg;
671
672 int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
673 int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
674
675 __ bind(restart);
676
677 // Get the index into the update buffer. G1DirtyCardQueue::_index is
678 // a size_t so ld_ptr is appropriate here.
679 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3);
680
681 // index == 0?
682 __ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill);
683
684 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4);
685 __ sub(tmp3, oopSize, tmp3);
686
687 __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card>
688 // Use return-from-leaf
689 __ retl();
690 __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset);
691
692 __ bind(refill);
693
694 __ save_live_registers_no_oop_map(true);
695
696 __ call_VM_leaf(L7_thread_cache,
697 CAST_FROM_FN_PTR(address,
698 G1DirtyCardQueueSet::handle_zero_index_for_thread),
699 G2_thread);
700
701 __ restore_live_registers(true);
702
703 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
704 __ epilogue();
705 }
706
707 #undef __
708
709 #endif // COMPILER1
|