< prev index next >

src/hotspot/share/gc/g1/g1OopClosures.inline.hpp

Print this page
rev 57729 : 8235305: Corrupted oops embedded in nmethods due to parallel modification during optional evacuation
Summary: During optional evacuation it is possible that G1 modifies oops embedded in nmethods in parallel. One source are oop* gathered by a previous evacuation phase in the optional roots, the other the region's strong code roots list. Since these oops may be unaligned on x64, this can result in them being corrupted. The fix is to not gather embedded oops in the optional roots list as the strong code roots list contains them already.
Contributed-by: erik.osterlund@oracle.com, stefan.johansson@oracle.com, stefan.karlsson@oracle.com, thomas.schatzl@oracle.com
Reviewed-by:
rev 57730 : [mq]: 8235305-sjohanss-review


 229   assert(_worker_id == _par_scan_state->worker_id(), "sanity");
 230 
 231   const G1HeapRegionAttr state = _g1h->region_attr(obj);
 232   if (state.is_in_cset()) {
 233     oop forwardee;
 234     markWord m = obj->mark_raw();
 235     if (m.is_marked()) {
 236       forwardee = (oop) m.decode_pointer();
 237     } else {
 238       forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
 239     }
 240     assert(forwardee != NULL, "forwardee should not be NULL");
 241     RawAccess<IS_NOT_NULL>::oop_store(p, forwardee);
 242 
 243     if (barrier == G1BarrierCLD) {
 244       do_cld_barrier(forwardee);
 245     }
 246   } else {
 247     if (state.is_humongous()) {
 248       _g1h->set_humongous_is_live(obj);
 249     } else if ((barrier != G1BarrierNoOptRoots) && state.is_optional()) {







 250       _par_scan_state->remember_root_into_optional_region(p);

 251     }
 252 
 253     // The object is not in collection set. If we're a root scanning
 254     // closure during an initial mark pause then attempt to mark the object.
 255     if (do_mark_object == G1MarkFromRoot) {
 256       mark_object(obj);
 257     }
 258   }
 259   trim_queue_partially();
 260 }
 261 
 262 template <class T> void G1RebuildRemSetClosure::do_oop_work(T* p) {
 263   oop const obj = RawAccess<MO_VOLATILE>::oop_load(p);
 264   if (obj == NULL) {
 265     return;
 266   }
 267 
 268   if (HeapRegion::is_in_same_region(p, obj)) {
 269     return;
 270   }


 229   assert(_worker_id == _par_scan_state->worker_id(), "sanity");
 230 
 231   const G1HeapRegionAttr state = _g1h->region_attr(obj);
 232   if (state.is_in_cset()) {
 233     oop forwardee;
 234     markWord m = obj->mark_raw();
 235     if (m.is_marked()) {
 236       forwardee = (oop) m.decode_pointer();
 237     } else {
 238       forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
 239     }
 240     assert(forwardee != NULL, "forwardee should not be NULL");
 241     RawAccess<IS_NOT_NULL>::oop_store(p, forwardee);
 242 
 243     if (barrier == G1BarrierCLD) {
 244       do_cld_barrier(forwardee);
 245     }
 246   } else {
 247     if (state.is_humongous()) {
 248       _g1h->set_humongous_is_live(obj);
 249     } else if (state.is_optional()) {
 250       // Skip collecting oops from nmethods into the optional collection set as
 251       // we already collect the corresponding nmethods in the region's strong code
 252       // roots set.
 253       // If these were present there would be opportunity for multiple threads to try
 254       // to change this oop* at the same time. Since embedded oops are not necessarily
 255       // word-aligned, this could lead to word tearing during update and crashes.
 256       if (barrier != G1BarrierNMethod) {
 257         _par_scan_state->remember_root_into_optional_region(p);
 258       }
 259     }
 260 
 261     // The object is not in collection set. If we're a root scanning
 262     // closure during an initial mark pause then attempt to mark the object.
 263     if (do_mark_object == G1MarkFromRoot) {
 264       mark_object(obj);
 265     }
 266   }
 267   trim_queue_partially();
 268 }
 269 
 270 template <class T> void G1RebuildRemSetClosure::do_oop_work(T* p) {
 271   oop const obj = RawAccess<MO_VOLATILE>::oop_load(p);
 272   if (obj == NULL) {
 273     return;
 274   }
 275 
 276   if (HeapRegion::is_in_same_region(p, obj)) {
 277     return;
 278   }
< prev index next >