comparison src/cpu/x86/vm/assembler_x86.cpp @ 3249:e1162778c1c8

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer. Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author johnc
date Thu, 07 Apr 2011 09:53:20 -0700
parents 8033953d67ff
children 92add02409c9
comparison
equal deleted inserted replaced
3248:e6beb62de02d 3249:e1162778c1c8
6888 6888
6889 ////////////////////////////////////////////////////////////////////////////////// 6889 //////////////////////////////////////////////////////////////////////////////////
6890 #ifndef SERIALGC 6890 #ifndef SERIALGC
6891 6891
6892 void MacroAssembler::g1_write_barrier_pre(Register obj, 6892 void MacroAssembler::g1_write_barrier_pre(Register obj,
6893 #ifndef _LP64 6893 Register pre_val,
6894 Register thread, 6894 Register thread,
6895 #endif
6896 Register tmp, 6895 Register tmp,
6897 Register tmp2, 6896 bool tosca_live,
6898 bool tosca_live) { 6897 bool expand_call) {
6899 LP64_ONLY(Register thread = r15_thread;) 6898
6899 // If expand_call is true then we expand the call_VM_leaf macro
6900 // directly to skip generating the check by
6901 // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
6902
6903 #ifdef _LP64
6904 assert(thread == r15_thread, "must be");
6905 #endif // _LP64
6906
6907 Label done;
6908 Label runtime;
6909
6910 assert(pre_val != noreg, "check this code");
6911
6912 if (obj != noreg) {
6913 assert_different_registers(obj, pre_val, tmp);
6914 assert(pre_val != rax, "check this code");
6915 }
6916
6900 Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + 6917 Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
6901 PtrQueue::byte_offset_of_active())); 6918 PtrQueue::byte_offset_of_active()));
6902
6903 Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + 6919 Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
6904 PtrQueue::byte_offset_of_index())); 6920 PtrQueue::byte_offset_of_index()));
6905 Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + 6921 Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
6906 PtrQueue::byte_offset_of_buf())); 6922 PtrQueue::byte_offset_of_buf()));
6907 6923
6908 6924
6909 Label done; 6925 // Is marking active?
6910 Label runtime;
6911
6912 // if (!marking_in_progress) goto done;
6913 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { 6926 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) {
6914 cmpl(in_progress, 0); 6927 cmpl(in_progress, 0);
6915 } else { 6928 } else {
6916 assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); 6929 assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption");
6917 cmpb(in_progress, 0); 6930 cmpb(in_progress, 0);
6918 } 6931 }
6919 jcc(Assembler::equal, done); 6932 jcc(Assembler::equal, done);
6920 6933
6921 // if (x.f == NULL) goto done; 6934 // Do we need to load the previous value?
6922 #ifdef _LP64 6935 if (obj != noreg) {
6923 load_heap_oop(tmp2, Address(obj, 0)); 6936 load_heap_oop(pre_val, Address(obj, 0));
6924 #else 6937 }
6925 movptr(tmp2, Address(obj, 0)); 6938
6926 #endif 6939 // Is the previous value null?
6927 cmpptr(tmp2, (int32_t) NULL_WORD); 6940 cmpptr(pre_val, (int32_t) NULL_WORD);
6928 jcc(Assembler::equal, done); 6941 jcc(Assembler::equal, done);
6929 6942
6930 // Can we store original value in the thread's buffer? 6943 // Can we store original value in the thread's buffer?
6931 6944 // Is index == 0?
6932 #ifdef _LP64 6945 // (The index field is typed as size_t.)
6933 movslq(tmp, index); 6946
6934 cmpq(tmp, 0); 6947 movptr(tmp, index); // tmp := *index_adr
6935 #else 6948 cmpptr(tmp, 0); // tmp == 0?
6936 cmpl(index, 0); 6949 jcc(Assembler::equal, runtime); // If yes, goto runtime
6937 #endif 6950
6938 jcc(Assembler::equal, runtime); 6951 subptr(tmp, wordSize); // tmp := tmp - wordSize
6939 #ifdef _LP64 6952 movptr(index, tmp); // *index_adr := tmp
6940 subq(tmp, wordSize); 6953 addptr(tmp, buffer); // tmp := tmp + *buffer_adr
6941 movl(index, tmp); 6954
6942 addq(tmp, buffer); 6955 // Record the previous value
6943 #else 6956 movptr(Address(tmp, 0), pre_val);
6944 subl(index, wordSize);
6945 movl(tmp, buffer);
6946 addl(tmp, index);
6947 #endif
6948 movptr(Address(tmp, 0), tmp2);
6949 jmp(done); 6957 jmp(done);
6958
6950 bind(runtime); 6959 bind(runtime);
6951 // save the live input values 6960 // save the live input values
6952 if(tosca_live) push(rax); 6961 if(tosca_live) push(rax);
6953 push(obj); 6962
6954 #ifdef _LP64 6963 if (obj != noreg && obj != rax)
6955 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, r15_thread); 6964 push(obj);
6956 #else 6965
6957 push(thread); 6966 if (pre_val != rax)
6958 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, thread); 6967 push(pre_val);
6959 pop(thread); 6968
6960 #endif 6969 // Calling the runtime using the regular call_VM_leaf mechanism generates
6961 pop(obj); 6970 // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
6971 // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
6972 //
6973 // If we care generating the pre-barrier without a frame (e.g. in the
6974 // intrinsified Reference.get() routine) then ebp might be pointing to
6975 // the caller frame and so this check will most likely fail at runtime.
6976 //
6977 // Expanding the call directly bypasses the generation of the check.
6978 // So when we do not have have a full interpreter frame on the stack
6979 // expand_call should be passed true.
6980
6981 NOT_LP64( push(thread); )
6982
6983 if (expand_call) {
6984 LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
6985 pass_arg1(this, thread);
6986 pass_arg0(this, pre_val);
6987 MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2);
6988 } else {
6989 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
6990 }
6991
6992 NOT_LP64( pop(thread); )
6993
6994 // save the live input values
6995 if (pre_val != rax)
6996 pop(pre_val);
6997
6998 if (obj != noreg && obj != rax)
6999 pop(obj);
7000
6962 if(tosca_live) pop(rax); 7001 if(tosca_live) pop(rax);
7002
6963 bind(done); 7003 bind(done);
6964
6965 } 7004 }
6966 7005
6967 void MacroAssembler::g1_write_barrier_post(Register store_addr, 7006 void MacroAssembler::g1_write_barrier_post(Register store_addr,
6968 Register new_val, 7007 Register new_val,
6969 #ifndef _LP64
6970 Register thread, 7008 Register thread,
6971 #endif
6972 Register tmp, 7009 Register tmp,
6973 Register tmp2) { 7010 Register tmp2) {
6974 7011 #ifdef _LP64
6975 LP64_ONLY(Register thread = r15_thread;) 7012 assert(thread == r15_thread, "must be");
7013 #endif // _LP64
7014
6976 Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + 7015 Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
6977 PtrQueue::byte_offset_of_index())); 7016 PtrQueue::byte_offset_of_index()));
6978 Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + 7017 Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
6979 PtrQueue::byte_offset_of_buf())); 7018 PtrQueue::byte_offset_of_buf()));
7019
6980 BarrierSet* bs = Universe::heap()->barrier_set(); 7020 BarrierSet* bs = Universe::heap()->barrier_set();
6981 CardTableModRefBS* ct = (CardTableModRefBS*)bs; 7021 CardTableModRefBS* ct = (CardTableModRefBS*)bs;
6982 Label done; 7022 Label done;
6983 Label runtime; 7023 Label runtime;
6984 7024
7053 #endif 7093 #endif
7054 pop(new_val); 7094 pop(new_val);
7055 pop(store_addr); 7095 pop(store_addr);
7056 7096
7057 bind(done); 7097 bind(done);
7058
7059 } 7098 }
7060 7099
7061 #endif // SERIALGC 7100 #endif // SERIALGC
7062 ////////////////////////////////////////////////////////////////////////////////// 7101 //////////////////////////////////////////////////////////////////////////////////
7063 7102