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