Mercurial > hg > graal-jvmci-8
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 |