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;
|