24 #include "precompiled.hpp"
25 #include "gc/shenandoah/brooksPointer.hpp"
26 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
27 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
28 #include "gc/shenandoah/shenandoahHeapRegion.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 #include "utilities/macros.hpp"
36 #ifdef COMPILER1
37 #include "c1/c1_LIRAssembler.hpp"
38 #include "c1/c1_MacroAssembler.hpp"
39 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
40 #endif
41
42 #define __ masm->
43
44 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
45 Register src, Register dst, Register count) {
46
47 bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
48 bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0;
49 bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops);
50 bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
51
52 if (type == T_OBJECT || type == T_ARRAY) {
53 #ifdef _LP64
54 if (!checkcast && !obj_int) {
55 // Save count for barrier
56 __ movptr(r11, count);
57 } else if (disjoint && obj_int) {
58 // Save dst in r11 in the disjoint case
59 __ movq(r11, dst);
60 }
61 #else
62 if (disjoint) {
63 __ mov(rdx, dst); // save 'to'
821 __ save_live_registers_no_oop_map(true);
822
823 // load the pre-value
824 __ load_parameter(0, rcx);
825 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), rcx, thread);
826
827 __ restore_live_registers(true);
828
829 __ bind(done);
830
831 __ pop(rdx);
832 __ pop(rax);
833
834 __ epilogue();
835 }
836
837 #undef __
838
839 #endif // COMPILER1
840
|
24 #include "precompiled.hpp"
25 #include "gc/shenandoah/brooksPointer.hpp"
26 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
27 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
28 #include "gc/shenandoah/shenandoahHeapRegion.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 #include "utilities/macros.hpp"
36 #ifdef COMPILER1
37 #include "c1/c1_LIRAssembler.hpp"
38 #include "c1/c1_MacroAssembler.hpp"
39 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
40 #endif
41
42 #define __ masm->
43
44 address ShenandoahBarrierSetAssembler::_shenandoah_wb = NULL;
45 address ShenandoahBarrierSetAssembler::_shenandoah_wb_C = NULL;
46
47 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
48 Register src, Register dst, Register count) {
49
50 bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
51 bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0;
52 bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops);
53 bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
54
55 if (type == T_OBJECT || type == T_ARRAY) {
56 #ifdef _LP64
57 if (!checkcast && !obj_int) {
58 // Save count for barrier
59 __ movptr(r11, count);
60 } else if (disjoint && obj_int) {
61 // Save dst in r11 in the disjoint case
62 __ movq(r11, dst);
63 }
64 #else
65 if (disjoint) {
66 __ mov(rdx, dst); // save 'to'
824 __ save_live_registers_no_oop_map(true);
825
826 // load the pre-value
827 __ load_parameter(0, rcx);
828 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), rcx, thread);
829
830 __ restore_live_registers(true);
831
832 __ bind(done);
833
834 __ pop(rdx);
835 __ pop(rax);
836
837 __ epilogue();
838 }
839
840 #undef __
841
842 #endif // COMPILER1
843
844 address ShenandoahBarrierSetAssembler::shenandoah_wb() {
845 return _shenandoah_wb;
846 }
847
848 address ShenandoahBarrierSetAssembler::shenandoah_wb_C() {
849 return _shenandoah_wb_C;
850 }
851
852 #define __ cgen->assembler()->
853
854 address ShenandoahBarrierSetAssembler::generate_shenandoah_wb(StubCodeGenerator* cgen, bool c_abi, bool do_cset_test) {
855 __ align(CodeEntryAlignment);
856 StubCodeMark mark(cgen, "StubRoutines", "shenandoah_wb");
857 address start = __ pc();
858
859 Label not_done;
860
861 // We use RDI, which also serves as argument register for slow call.
862 // RAX always holds the src object ptr, except after the slow call and
863 // the cmpxchg, then it holds the result.
864 // R8 and RCX are used as temporary registers.
865 if (!c_abi) {
866 __ push(rdi);
867 __ push(r8);
868 }
869
870 // Check for object beeing in the collection set.
871 // TODO: Can we use only 1 register here?
872 // The source object arrives here in rax.
873 // live: rax
874 // live: rdi
875 if (!c_abi) {
876 __ mov(rdi, rax);
877 } else {
878 if (rax != c_rarg0) {
879 __ mov(rax, c_rarg0);
880 }
881 }
882 if (do_cset_test) {
883 __ shrptr(rdi, ShenandoahHeapRegion::region_size_bytes_shift_jint());
884 // live: r8
885 __ movptr(r8, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr());
886 __ movbool(r8, Address(r8, rdi, Address::times_1));
887 // unlive: rdi
888 __ testbool(r8);
889 // unlive: r8
890 __ jccb(Assembler::notZero, not_done);
891
892 if (!c_abi) {
893 __ pop(r8);
894 __ pop(rdi);
895 }
896 __ ret(0);
897
898 __ bind(not_done);
899 }
900
901 if (!c_abi) {
902 __ push(rcx);
903 }
904
905 if (!c_abi) {
906 __ push(rdx);
907 __ push(rdi);
908 __ push(rsi);
909 __ push(r8);
910 __ push(r9);
911 __ push(r10);
912 __ push(r11);
913 __ push(r12);
914 __ push(r13);
915 __ push(r14);
916 __ push(r15);
917 }
918 __ save_vector_registers();
919 __ movptr(rdi, rax);
920 __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_JRT), rdi);
921 __ restore_vector_registers();
922 if (!c_abi) {
923 __ pop(r15);
924 __ pop(r14);
925 __ pop(r13);
926 __ pop(r12);
927 __ pop(r11);
928 __ pop(r10);
929 __ pop(r9);
930 __ pop(r8);
931 __ pop(rsi);
932 __ pop(rdi);
933 __ pop(rdx);
934
935 __ pop(rcx);
936 __ pop(r8);
937 __ pop(rdi);
938 }
939 __ ret(0);
940
941 return start;
942 }
943
944 #undef __
945
946 void ShenandoahBarrierSetAssembler::barrier_stubs_init() {
947 if (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier) {
948 int stub_code_size = 1536;
949 ResourceMark rm;
950 BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size);
951 CodeBuffer buf(bb);
952 StubCodeGenerator cgen(&buf);
953 _shenandoah_wb = generate_shenandoah_wb(&cgen, false, true);
954 _shenandoah_wb_C = generate_shenandoah_wb(&cgen, true, !ShenandoahWriteBarrierCsetTestInIR);
955 }
956 }
|