Mercurial > hg > graal-compiler
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(); |