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 "asm/macroAssembler.inline.hpp"
26 #include "gc/g1/g1BarrierSet.hpp"
27 #include "gc/g1/g1BarrierSetAssembler.hpp"
28 #include "gc/g1/g1BarrierSetRuntime.hpp"
29 #include "gc/g1/g1CardTable.hpp"
30 #include "gc/g1/g1HeapRegion.hpp"
31 #include "gc/g1/g1ThreadLocalData.hpp"
32 #include "interpreter/interp_masm.hpp"
33 #include "runtime/sharedRuntime.hpp"
34 #include "utilities/debug.hpp"
35 #include "utilities/macros.hpp"
36 #ifdef COMPILER1
37 #include "c1/c1_LIRAssembler.hpp"
38 #include "c1/c1_MacroAssembler.hpp"
39 #include "gc/g1/c1/g1BarrierSetC1.hpp"
40 #endif // COMPILER1
41 #ifdef COMPILER2
42 #include "gc/g1/c2/g1BarrierSetC2.hpp"
43 #endif // COMPILER2
44
45 #define __ masm->
265 if (c_rarg1 != thread) {
266 __ mov(c_rarg1, thread);
267 }
268 if (c_rarg0 != pre_val) {
269 __ mov(c_rarg0, pre_val);
270 }
271 #else
272 __ push(thread);
273 __ push(pre_val);
274 #endif
275 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
276 } else {
277 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
278 }
279
280 __ pop_call_clobbered_registers();
281
282 __ bind(done);
283 }
284
285 static void generate_post_barrier_fast_path(MacroAssembler* masm,
286 const Register store_addr,
287 const Register new_val,
288 const Register tmp,
289 const Register tmp2,
290 Label& done,
291 bool new_val_may_be_null) {
292 CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
293 // Does store cross heap regions?
294 __ movptr(tmp, store_addr); // tmp := store address
295 __ xorptr(tmp, new_val); // tmp := store address ^ new value
296 __ shrptr(tmp, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0?
297 __ jcc(Assembler::equal, done);
298 // Crosses regions, storing null?
299 if (new_val_may_be_null) {
300 __ cmpptr(new_val, NULL_WORD); // new value == null?
301 __ jcc(Assembler::equal, done);
302 }
303 // Storing region crossing non-null, is card young?
304 __ movptr(tmp, store_addr); // tmp := store address
305 __ shrptr(tmp, CardTable::card_shift()); // tmp := card address relative to card table base
306 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
307 // a valid address and therefore is not properly handled by the relocation code.
308 __ movptr(tmp2, (intptr_t)ct->card_table()->byte_map_base()); // tmp2 := card table base address
309 __ addptr(tmp, tmp2); // tmp := card address
310 __ cmpb(Address(tmp, 0), G1CardTable::g1_young_card_val()); // *(card address) == young_card_val?
311 }
312
313 static void generate_post_barrier_slow_path(MacroAssembler* masm,
314 const Register thread,
315 const Register tmp,
316 const Register tmp2,
317 Label& done,
318 Label& runtime) {
319 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); // StoreLoad membar
320 __ cmpb(Address(tmp, 0), G1CardTable::dirty_card_val()); // *(card address) == dirty_card_val?
321 __ jcc(Assembler::equal, done);
322 // Storing a region crossing, non-null oop, card is clean.
323 // Dirty card and log.
324 __ movb(Address(tmp, 0), G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val
325 generate_queue_insertion(masm,
326 G1ThreadLocalData::dirty_card_queue_index_offset(),
327 G1ThreadLocalData::dirty_card_queue_buffer_offset(),
328 runtime,
639 Label runtime;
640
641 // At this point we know new_value is non-null and the new_value crosses regions.
642 // Must check to see if card is already dirty
643
644 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
645
646 Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
647 Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
648
649 __ push(rax);
650 __ push(rcx);
651
652 const Register cardtable = rax;
653 const Register card_addr = rcx;
654
655 __ load_parameter(0, card_addr);
656 __ shrptr(card_addr, CardTable::card_shift());
657 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
658 // a valid address and therefore is not properly handled by the relocation code.
659 __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base());
660 __ addptr(card_addr, cardtable);
661
662 NOT_LP64(__ get_thread(thread);)
663
664 __ cmpb(Address(card_addr, 0), G1CardTable::g1_young_card_val());
665 __ jcc(Assembler::equal, done);
666
667 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
668 __ cmpb(Address(card_addr, 0), CardTable::dirty_card_val());
669 __ jcc(Assembler::equal, done);
670
671 // storing region crossing non-null, card is clean.
672 // dirty card and log.
673
674 __ movb(Address(card_addr, 0), CardTable::dirty_card_val());
675
676 const Register tmp = rdx;
677 __ push(rdx);
678
679 __ movptr(tmp, queue_index);
|
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 "asm/macroAssembler.inline.hpp"
26 #if INCLUDE_CDS
27 #include "code/SCCache.hpp"
28 #endif
29 #include "gc/g1/g1BarrierSet.hpp"
30 #include "gc/g1/g1BarrierSetAssembler.hpp"
31 #include "gc/g1/g1BarrierSetRuntime.hpp"
32 #include "gc/g1/g1CardTable.hpp"
33 #include "gc/g1/g1HeapRegion.hpp"
34 #include "gc/g1/g1ThreadLocalData.hpp"
35 #include "interpreter/interp_masm.hpp"
36 #include "runtime/sharedRuntime.hpp"
37 #include "utilities/debug.hpp"
38 #include "utilities/macros.hpp"
39 #ifdef COMPILER1
40 #include "c1/c1_LIRAssembler.hpp"
41 #include "c1/c1_MacroAssembler.hpp"
42 #include "gc/g1/c1/g1BarrierSetC1.hpp"
43 #endif // COMPILER1
44 #ifdef COMPILER2
45 #include "gc/g1/c2/g1BarrierSetC2.hpp"
46 #endif // COMPILER2
47
48 #define __ masm->
268 if (c_rarg1 != thread) {
269 __ mov(c_rarg1, thread);
270 }
271 if (c_rarg0 != pre_val) {
272 __ mov(c_rarg0, pre_val);
273 }
274 #else
275 __ push(thread);
276 __ push(pre_val);
277 #endif
278 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
279 } else {
280 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
281 }
282
283 __ pop_call_clobbered_registers();
284
285 __ bind(done);
286 }
287
288 // return a register that differs from reg1, reg2, reg3 and is not rcx
289
290 static Register pick_different_reg(Register reg1, Register reg2 = noreg, Register reg3= noreg, Register reg4 = noreg) {
291 RegSet available = (RegSet::of(rscratch1, rscratch2, rax, rbx) + rdx -
292 RegSet::of(reg1, reg2, reg3, reg4));
293 return *(available.begin());
294 }
295
296 static void generate_post_barrier_fast_path(MacroAssembler* masm,
297 const Register store_addr,
298 const Register new_val,
299 const Register tmp,
300 const Register tmp2,
301 Label& done,
302 bool new_val_may_be_null) {
303 CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
304 // Does store cross heap regions?
305 #if INCLUDE_CDS
306 // AOT code needs to load the barrier grain shift from the aot
307 // runtime constants area in the code cache otherwise we can compile
308 // it as an immediate operand
309
310 if (SCCache::is_on_for_write()) {
311 address grain_shift_addr = AOTRuntimeConstants::grain_shift_address();
312 Register save = pick_different_reg(rcx, tmp, new_val, store_addr);
313 __ push(save);
314 __ movptr(save, store_addr);
315 __ xorptr(save, new_val);
316 __ push(rcx);
317 __ lea(rcx, ExternalAddress(grain_shift_addr));
318 __ movptr(rcx, Address(rcx, 0));
319 __ shrptr(save);
320 __ pop(rcx);
321 __ mov(tmp, save);
322 __ pop(save);
323 __ jcc(Assembler::equal, done);
324 } else
325 #endif // INCLUDE_CDS
326 {
327 __ movptr(tmp, store_addr); // tmp := store address
328 __ xorptr(tmp, new_val); // tmp := store address ^ new value
329 __ shrptr(tmp, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0?
330 __ jcc(Assembler::equal, done);
331 }
332
333 // Crosses regions, storing null?
334 if (new_val_may_be_null) {
335 __ cmpptr(new_val, NULL_WORD); // new value == null?
336 __ jcc(Assembler::equal, done);
337 }
338 // Storing region crossing non-null, is card young?
339 __ movptr(tmp, store_addr); // tmp := store address
340 #if INCLUDE_CDS
341 // AOT code needs to load the barrier card shift from the aot
342 // runtime constants area in the code cache otherwise we can compile
343 // it as an immediate operand
344 if (SCCache::is_on_for_write()) {
345 address card_shift_addr = AOTRuntimeConstants::card_shift_address();
346 Register save = pick_different_reg(rcx, tmp);
347 __ push(save);
348 __ mov(save, tmp);
349 __ push(rcx);
350 __ lea(rcx, ExternalAddress(card_shift_addr));
351 __ movptr(rcx, Address(rcx, 0));
352 __ shrptr(save);
353 __ pop(rcx);
354 __ mov(tmp, save);
355 __ pop(save);
356 } else
357 #endif // INCLUDE_CDS
358 {
359 __ shrptr(tmp, CardTable::card_shift()); // tmp := card address relative to card table base
360 }
361 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
362 // a valid address and therefore is not properly handled by the relocation code.
363 if (SCCache::is_on_for_write()) {
364 // SCA needs relocation info for this address
365 __ lea(tmp2, ExternalAddress((address)ct->card_table()->byte_map_base())); // tmp2 := card table base address
366 } else {
367 __ movptr(tmp2, (intptr_t)ct->card_table()->byte_map_base()); // tmp2 := card table base address
368 }
369 __ addptr(tmp, tmp2); // tmp := card address
370 __ cmpb(Address(tmp, 0), G1CardTable::g1_young_card_val()); // *(card address) == young_card_val?
371 }
372
373 static void generate_post_barrier_slow_path(MacroAssembler* masm,
374 const Register thread,
375 const Register tmp,
376 const Register tmp2,
377 Label& done,
378 Label& runtime) {
379 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); // StoreLoad membar
380 __ cmpb(Address(tmp, 0), G1CardTable::dirty_card_val()); // *(card address) == dirty_card_val?
381 __ jcc(Assembler::equal, done);
382 // Storing a region crossing, non-null oop, card is clean.
383 // Dirty card and log.
384 __ movb(Address(tmp, 0), G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val
385 generate_queue_insertion(masm,
386 G1ThreadLocalData::dirty_card_queue_index_offset(),
387 G1ThreadLocalData::dirty_card_queue_buffer_offset(),
388 runtime,
699 Label runtime;
700
701 // At this point we know new_value is non-null and the new_value crosses regions.
702 // Must check to see if card is already dirty
703
704 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
705
706 Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
707 Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
708
709 __ push(rax);
710 __ push(rcx);
711
712 const Register cardtable = rax;
713 const Register card_addr = rcx;
714
715 __ load_parameter(0, card_addr);
716 __ shrptr(card_addr, CardTable::card_shift());
717 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
718 // a valid address and therefore is not properly handled by the relocation code.
719 if (SCCache::is_on()) {
720 // SCA needs relocation info for this address
721 __ lea(cardtable, ExternalAddress((address)ct->card_table()->byte_map_base()));
722 } else {
723 __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base());
724 }
725 __ addptr(card_addr, cardtable);
726
727 NOT_LP64(__ get_thread(thread);)
728
729 __ cmpb(Address(card_addr, 0), G1CardTable::g1_young_card_val());
730 __ jcc(Assembler::equal, done);
731
732 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
733 __ cmpb(Address(card_addr, 0), CardTable::dirty_card_val());
734 __ jcc(Assembler::equal, done);
735
736 // storing region crossing non-null, card is clean.
737 // dirty card and log.
738
739 __ movb(Address(card_addr, 0), CardTable::dirty_card_val());
740
741 const Register tmp = rdx;
742 __ push(rdx);
743
744 __ movptr(tmp, queue_index);
|