< prev index next >

src/hotspot/share/gc/g1/g1SharedClosures.hpp

Print this page
rev 57716 : 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:


  23  */
  24 
  25 #include "gc/g1/g1CodeBlobClosure.hpp"
  26 #include "gc/g1/g1OopClosures.hpp"
  27 #include "memory/iterator.hpp"
  28 
  29 class G1CollectedHeap;
  30 class G1ParScanThreadState;
  31 
  32 // Simple holder object for a complete set of closures used by the G1 evacuation code.
  33 template <G1Mark Mark>
  34 class G1SharedClosures {
  35   static bool needs_strong_processing() {
  36     // Request strong code root processing when G1MarkFromRoot is passed in during
  37     // initial mark.
  38     return Mark == G1MarkFromRoot;
  39   }
  40 public:
  41   G1ParCopyClosure<G1BarrierNone, Mark> _oops;
  42   G1ParCopyClosure<G1BarrierCLD,  Mark> _oops_in_cld;








  43 
  44   G1CLDScanClosure                _clds;
  45   G1CodeBlobClosure               _codeblobs;
  46 
  47   G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty) :
  48     _oops(g1h, pss),
  49     _oops_in_cld(g1h, pss),

  50     _clds(&_oops_in_cld, process_only_dirty),
  51     _codeblobs(pss->worker_id(), &_oops, needs_strong_processing()) {}
  52 };


  23  */
  24 
  25 #include "gc/g1/g1CodeBlobClosure.hpp"
  26 #include "gc/g1/g1OopClosures.hpp"
  27 #include "memory/iterator.hpp"
  28 
  29 class G1CollectedHeap;
  30 class G1ParScanThreadState;
  31 
  32 // Simple holder object for a complete set of closures used by the G1 evacuation code.
  33 template <G1Mark Mark>
  34 class G1SharedClosures {
  35   static bool needs_strong_processing() {
  36     // Request strong code root processing when G1MarkFromRoot is passed in during
  37     // initial mark.
  38     return Mark == G1MarkFromRoot;
  39   }
  40 public:
  41   G1ParCopyClosure<G1BarrierNone, Mark> _oops;
  42   G1ParCopyClosure<G1BarrierCLD,  Mark> _oops_in_cld;
  43   // We do not need (and actually should not) collect oops from nmethods into the
  44   // optional collection set as we already automatically collect the corresponding
  45   // nmethods in the region's strong code roots set. So set G1BarrierNoOptRoots in
  46   // this closure.
  47   // If these were present there would be opportunity for multiple threads to try
  48   // to change this oop* at the same time. Since embedded oops are not necessarily
  49   // word-aligned, this could lead to word tearing during update and crashes.
  50   G1ParCopyClosure<G1BarrierNoOptRoots, Mark> _oops_in_nmethod;
  51 
  52   G1CLDScanClosure                _clds;
  53   G1CodeBlobClosure               _codeblobs;
  54 
  55   G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty) :
  56     _oops(g1h, pss),
  57     _oops_in_cld(g1h, pss),
  58     _oops_in_nmethod(g1h, pss),
  59     _clds(&_oops_in_cld, process_only_dirty),
  60     _codeblobs(pss->worker_id(), &_oops_in_nmethod, needs_strong_processing()) {}
  61 };
< prev index next >