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