24 #include "precompiled.hpp"
25 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
26 #include "gc/shenandoah/shenandoahHeap.hpp"
27 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
28 #include "gc/shenandoah/shenandoahHeuristics.hpp"
29 #include "gc/shenandoah/shenandoahRuntime.hpp"
30 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
31 #include "interpreter/interpreter.hpp"
32 #include "interpreter/interp_masm.hpp"
33 #include "runtime/sharedRuntime.hpp"
34 #include "runtime/thread.hpp"
35 #ifdef COMPILER1
36 #include "c1/c1_LIRAssembler.hpp"
37 #include "c1/c1_MacroAssembler.hpp"
38 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
39 #endif
40
41 #define __ masm->
42
43 address ShenandoahBarrierSetAssembler::_shenandoah_wb = NULL;
44 address ShenandoahBarrierSetAssembler::_shenandoah_wb_C = NULL;
45
46 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
47 Register addr, Register count, RegSet saved_regs) {
48 if (is_oop) {
49 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
50 if (!dest_uninitialized && !ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc()) {
51 __ push(saved_regs, sp);
52 if (count == c_rarg0) {
53 if (addr == c_rarg1) {
54 // exactly backwards!!
55 __ mov(rscratch1, c_rarg0);
56 __ mov(c_rarg0, c_rarg1);
57 __ mov(c_rarg1, rscratch1);
58 } else {
59 __ mov(c_rarg1, count);
60 __ mov(c_rarg0, addr);
61 }
62 } else {
63 __ mov(c_rarg0, addr);
64 __ mov(c_rarg1, count);
600
601 __ bind(runtime);
602 __ push_call_clobbered_registers();
603 __ load_parameter(0, pre_val);
604 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread);
605 __ pop_call_clobbered_registers();
606 __ bind(done);
607
608 __ epilogue();
609 }
610
611 #undef __
612
613 #endif // COMPILER1
614
615 address ShenandoahBarrierSetAssembler::shenandoah_wb() {
616 assert(_shenandoah_wb != NULL, "need write barrier stub");
617 return _shenandoah_wb;
618 }
619
620 address ShenandoahBarrierSetAssembler::shenandoah_wb_C() {
621 assert(_shenandoah_wb_C != NULL, "need write barrier stub");
622 return _shenandoah_wb_C;
623 }
624
625 #define __ cgen->assembler()->
626
627 // Shenandoah write barrier.
628 //
629 // Input:
630 // r0: OOP to evacuate. Not null.
631 //
632 // Output:
633 // r0: Pointer to evacuated OOP.
634 //
635 // Trash rscratch1, rscratch2. Preserve everything else.
636 address ShenandoahBarrierSetAssembler::generate_shenandoah_wb(StubCodeGenerator* cgen, bool c_abi, bool do_cset_test) {
637
638 __ align(6);
639 StubCodeMark mark(cgen, "StubRoutines", "shenandoah_wb");
640 address start = __ pc();
641
642 if (do_cset_test) {
643 Label work;
644 __ mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
645 __ lsr(rscratch1, r0, ShenandoahHeapRegion::region_size_bytes_shift_jint());
646 __ ldrb(rscratch2, Address(rscratch2, rscratch1));
647 __ tbnz(rscratch2, 0, work);
648 __ ret(lr);
649 __ bind(work);
650 }
651
652 Register obj = r0;
653
654 __ enter(); // required for proper stackwalking of RuntimeStub frame
655
656 if (!c_abi) {
657 __ push_call_clobbered_registers();
658 } else {
659 __ push_call_clobbered_fp_registers();
660 }
661
662 __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT));
663 __ blrt(lr, 1, 0, MacroAssembler::ret_type_integral);
664 if (!c_abi) {
665 __ mov(rscratch1, obj);
666 __ pop_call_clobbered_registers();
667 __ mov(obj, rscratch1);
668 } else {
669 __ pop_call_clobbered_fp_registers();
670 }
671
672 __ leave(); // required for proper stackwalking of RuntimeStub frame
673 __ ret(lr);
674
675 return start;
676 }
677
678 #undef __
679
680 void ShenandoahBarrierSetAssembler::barrier_stubs_init() {
681 if (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier) {
682 int stub_code_size = 2048;
683 ResourceMark rm;
684 BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size);
685 CodeBuffer buf(bb);
686 StubCodeGenerator cgen(&buf);
687 _shenandoah_wb = generate_shenandoah_wb(&cgen, false, true);
688 _shenandoah_wb_C = generate_shenandoah_wb(&cgen, true, false);
689 }
690 }
|
24 #include "precompiled.hpp"
25 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
26 #include "gc/shenandoah/shenandoahHeap.hpp"
27 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
28 #include "gc/shenandoah/shenandoahHeuristics.hpp"
29 #include "gc/shenandoah/shenandoahRuntime.hpp"
30 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
31 #include "interpreter/interpreter.hpp"
32 #include "interpreter/interp_masm.hpp"
33 #include "runtime/sharedRuntime.hpp"
34 #include "runtime/thread.hpp"
35 #ifdef COMPILER1
36 #include "c1/c1_LIRAssembler.hpp"
37 #include "c1/c1_MacroAssembler.hpp"
38 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
39 #endif
40
41 #define __ masm->
42
43 address ShenandoahBarrierSetAssembler::_shenandoah_wb = NULL;
44
45 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
46 Register addr, Register count, RegSet saved_regs) {
47 if (is_oop) {
48 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
49 if (!dest_uninitialized && !ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc()) {
50 __ push(saved_regs, sp);
51 if (count == c_rarg0) {
52 if (addr == c_rarg1) {
53 // exactly backwards!!
54 __ mov(rscratch1, c_rarg0);
55 __ mov(c_rarg0, c_rarg1);
56 __ mov(c_rarg1, rscratch1);
57 } else {
58 __ mov(c_rarg1, count);
59 __ mov(c_rarg0, addr);
60 }
61 } else {
62 __ mov(c_rarg0, addr);
63 __ mov(c_rarg1, count);
599
600 __ bind(runtime);
601 __ push_call_clobbered_registers();
602 __ load_parameter(0, pre_val);
603 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread);
604 __ pop_call_clobbered_registers();
605 __ bind(done);
606
607 __ epilogue();
608 }
609
610 #undef __
611
612 #endif // COMPILER1
613
614 address ShenandoahBarrierSetAssembler::shenandoah_wb() {
615 assert(_shenandoah_wb != NULL, "need write barrier stub");
616 return _shenandoah_wb;
617 }
618
619 #define __ cgen->assembler()->
620
621 // Shenandoah write barrier.
622 //
623 // Input:
624 // r0: OOP to evacuate. Not null.
625 //
626 // Output:
627 // r0: Pointer to evacuated OOP.
628 //
629 // Trash rscratch1, rscratch2. Preserve everything else.
630 address ShenandoahBarrierSetAssembler::generate_shenandoah_wb(StubCodeGenerator* cgen) {
631
632 __ align(6);
633 StubCodeMark mark(cgen, "StubRoutines", "shenandoah_wb");
634 address start = __ pc();
635
636 Label work;
637 __ mov(rscratch2, ShenandoahHeap::in_cset_fast_test_addr());
638 __ lsr(rscratch1, r0, ShenandoahHeapRegion::region_size_bytes_shift_jint());
639 __ ldrb(rscratch2, Address(rscratch2, rscratch1));
640 __ tbnz(rscratch2, 0, work);
641 __ ret(lr);
642 __ bind(work);
643
644 Register obj = r0;
645
646 __ enter(); // required for proper stackwalking of RuntimeStub frame
647
648 __ push_call_clobbered_registers();
649
650 __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT));
651 __ blrt(lr, 1, 0, MacroAssembler::ret_type_integral);
652 __ mov(rscratch1, obj);
653 __ pop_call_clobbered_registers();
654 __ mov(obj, rscratch1);
655
656 __ leave(); // required for proper stackwalking of RuntimeStub frame
657 __ ret(lr);
658
659 return start;
660 }
661
662 #undef __
663
664 void ShenandoahBarrierSetAssembler::barrier_stubs_init() {
665 if (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier) {
666 int stub_code_size = 2048;
667 ResourceMark rm;
668 BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size);
669 CodeBuffer buf(bb);
670 StubCodeGenerator cgen(&buf);
671 _shenandoah_wb = generate_shenandoah_wb(&cgen);
672 }
673 }
|