< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp

Print this page
rev 60126 : 8247670: Shenandoah: deadlock during class unloading OOME


 256       return;
 257     }
 258 
 259     ShenandoahNMethod* nm_data = ShenandoahNMethod::gc_data(nm);
 260     assert(!nm_data->is_unregistered(), "Should not see unregistered entry");
 261 
 262     if (!nm->is_alive()) {
 263       return;
 264     }
 265 
 266     if (nm->is_unloading()) {
 267       ShenandoahReentrantLocker locker(nm_data->lock());
 268       unlink(nm);
 269       return;
 270     }
 271 
 272     ShenandoahReentrantLocker locker(nm_data->lock());
 273 
 274     // Heal oops and disarm
 275     if (_bs->is_armed(nm)) {

 276       ShenandoahNMethod::heal_nmethod_metadata(nm_data);
 277       _bs->disarm(nm);
 278     }
 279 
 280     // Clear compiled ICs and exception caches
 281     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 282       set_failed();
 283     }
 284   }
 285 
 286   bool failed() const {
 287     return Atomic::load(&_failed);
 288   }
 289 };
 290 
 291 class ShenandoahUnlinkTask : public AbstractGangTask {
 292 private:
 293   ShenandoahNMethodUnlinkClosure      _cl;
 294   ICRefillVerifier*                   _verifier;
 295   ShenandoahConcurrentNMethodIterator _iterator;
 296 
 297 public:
 298   ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 299     AbstractGangTask("ShenandoahNMethodUnlinkTask"),
 300     _cl(unloading_occurred),
 301     _verifier(verifier),
 302     _iterator(ShenandoahCodeRoots::table()) {
 303     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 304     _iterator.nmethods_do_begin();
 305   }
 306 
 307   ~ShenandoahUnlinkTask() {
 308     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 309     _iterator.nmethods_do_end();
 310   }
 311 
 312   virtual void work(uint worker_id) {
 313     ICRefillVerifierMark mark(_verifier);
 314     ShenandoahEvacOOMScope evac_scope;
 315     _iterator.nmethods_do(&_cl);
 316   }
 317 
 318   bool success() const {
 319     return !_cl.failed();
 320   }
 321 };
 322 
 323 void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
 324   assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
 325          "Only when running concurrent class unloading");
 326 
 327   for (;;) {
 328     ICRefillVerifier verifier;
 329 
 330     {
 331       ShenandoahUnlinkTask task(unloading_occurred, &verifier);
 332       workers->run_task(&task);
 333       if (task.success()) {
 334         return;




 256       return;
 257     }
 258 
 259     ShenandoahNMethod* nm_data = ShenandoahNMethod::gc_data(nm);
 260     assert(!nm_data->is_unregistered(), "Should not see unregistered entry");
 261 
 262     if (!nm->is_alive()) {
 263       return;
 264     }
 265 
 266     if (nm->is_unloading()) {
 267       ShenandoahReentrantLocker locker(nm_data->lock());
 268       unlink(nm);
 269       return;
 270     }
 271 
 272     ShenandoahReentrantLocker locker(nm_data->lock());
 273 
 274     // Heal oops and disarm
 275     if (_bs->is_armed(nm)) {
 276       ShenandoahEvacOOMScope oom_evac_scope;
 277       ShenandoahNMethod::heal_nmethod_metadata(nm_data);
 278       _bs->disarm(nm);
 279     }
 280 
 281     // Clear compiled ICs and exception caches
 282     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 283       set_failed();
 284     }
 285   }
 286 
 287   bool failed() const {
 288     return Atomic::load(&_failed);
 289   }
 290 };
 291 
 292 class ShenandoahUnlinkTask : public AbstractGangTask {
 293 private:
 294   ShenandoahNMethodUnlinkClosure      _cl;
 295   ICRefillVerifier*                   _verifier;
 296   ShenandoahConcurrentNMethodIterator _iterator;
 297 
 298 public:
 299   ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 300     AbstractGangTask("ShenandoahNMethodUnlinkTask"),
 301     _cl(unloading_occurred),
 302     _verifier(verifier),
 303     _iterator(ShenandoahCodeRoots::table()) {
 304     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 305     _iterator.nmethods_do_begin();
 306   }
 307 
 308   ~ShenandoahUnlinkTask() {
 309     MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 310     _iterator.nmethods_do_end();
 311   }
 312 
 313   virtual void work(uint worker_id) {
 314     ICRefillVerifierMark mark(_verifier);

 315     _iterator.nmethods_do(&_cl);
 316   }
 317 
 318   bool success() const {
 319     return !_cl.failed();
 320   }
 321 };
 322 
 323 void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
 324   assert(ShenandoahConcurrentRoots::should_do_concurrent_class_unloading(),
 325          "Only when running concurrent class unloading");
 326 
 327   for (;;) {
 328     ICRefillVerifier verifier;
 329 
 330     {
 331       ShenandoahUnlinkTask task(unloading_occurred, &verifier);
 332       workers->run_task(&task);
 333       if (task.success()) {
 334         return;


< prev index next >