comparison src/share/vm/c1/c1_GraphBuilder.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 c7f3d0b4570f
children 92add02409c9
comparison
equal deleted inserted replaced
3248:e6beb62de02d 3249:e1162778c1c8
2910 // connect the begin and end blocks and we're all done. 2910 // connect the begin and end blocks and we're all done.
2911 BlockEnd* end = last()->as_BlockEnd(); 2911 BlockEnd* end = last()->as_BlockEnd();
2912 block()->set_end(end); 2912 block()->set_end(end);
2913 break; 2913 break;
2914 } 2914 }
2915
2916 case vmIntrinsics::_Reference_get:
2917 {
2918 if (UseG1GC) {
2919 // With java.lang.ref.reference.get() we must go through the
2920 // intrinsic - when G1 is enabled - even when get() is the root
2921 // method of the compile so that, if necessary, the value in
2922 // the referent field of the reference object gets recorded by
2923 // the pre-barrier code.
2924 // Specifically, if G1 is enabled, the value in the referent
2925 // field is recorded by the G1 SATB pre barrier. This will
2926 // result in the referent being marked live and the reference
2927 // object removed from the list of discovered references during
2928 // reference processing.
2929
2930 // Set up a stream so that appending instructions works properly.
2931 ciBytecodeStream s(scope->method());
2932 s.reset_to_bci(0);
2933 scope_data()->set_stream(&s);
2934 s.next();
2935
2936 // setup the initial block state
2937 _block = start_block;
2938 _state = start_block->state()->copy_for_parsing();
2939 _last = start_block;
2940 load_local(objectType, 0);
2941
2942 // Emit the intrinsic node.
2943 bool result = try_inline_intrinsics(scope->method());
2944 if (!result) BAILOUT("failed to inline intrinsic");
2945 method_return(apop());
2946
2947 // connect the begin and end blocks and we're all done.
2948 BlockEnd* end = last()->as_BlockEnd();
2949 block()->set_end(end);
2950 break;
2951 }
2952 // Otherwise, fall thru
2953 }
2954
2915 default: 2955 default:
2916 scope_data()->add_to_work_list(start_block); 2956 scope_data()->add_to_work_list(start_block);
2917 iterate_all_blocks(); 2957 iterate_all_blocks();
2918 break; 2958 break;
2919 } 2959 }
3146 // fall through 3186 // fall through
3147 case vmIntrinsics::_compareAndSwapInt: 3187 case vmIntrinsics::_compareAndSwapInt:
3148 case vmIntrinsics::_compareAndSwapObject: 3188 case vmIntrinsics::_compareAndSwapObject:
3149 append_unsafe_CAS(callee); 3189 append_unsafe_CAS(callee);
3150 return true; 3190 return true;
3191
3192 case vmIntrinsics::_Reference_get:
3193 // It is only when G1 is enabled that we absolutely
3194 // need to use the intrinsic version of Reference.get()
3195 // so that the value in the referent field, if necessary,
3196 // can be registered by the pre-barrier code.
3197 if (!UseG1GC) return false;
3198 preserves_state = true;
3199 break;
3151 3200
3152 default : return false; // do not inline 3201 default : return false; // do not inline
3153 } 3202 }
3154 // create intrinsic node 3203 // create intrinsic node
3155 const bool has_receiver = !callee->is_static(); 3204 const bool has_receiver = !callee->is_static();