1 /*
   2  * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "classfile/stringTable.hpp"
  25 #include "gc/shared/gcTimer.hpp"
  26 #include "gc/shared/isGCActiveMark.hpp"
  27 #include "gc/shared/parallelCleaning.hpp"
  28 #include "gc/shared/strongRootsScope.hpp"
  29 #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp"
  30 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
  31 #include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
  32 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  33 #include "gc/shenandoah/shenandoahRootProcessor.hpp"
  34 #include "gc/shenandoah/shenandoah_specialized_oop_closures.hpp"
  35 #include "gc/shenandoah/brooksPointer.hpp"
  36 #include "gc/shared/referenceProcessor.hpp"
  37 #include "gc/shenandoah/shenandoahTaskqueue.hpp"
  38 #include "code/codeCache.hpp"
  39 #include "classfile/symbolTable.hpp"
  40 #include "classfile/systemDictionary.hpp"
  41 #include "memory/iterator.inline.hpp"
  42 #include "oops/oop.inline.hpp"
  43 #include "gc/shared/taskqueue.inline.hpp"
  44 
  45 class ShenandoahInitMarkRootsClosure : public OopClosure {
  46   SCMObjToScanQueue* _queue;
  47   ShenandoahHeap* _heap;
  48 
  49 public:
  50   ShenandoahInitMarkRootsClosure(SCMObjToScanQueue* q) :
  51     _queue(q),
  52     _heap((ShenandoahHeap*) Universe::heap())
  53   {
  54   }
  55 
  56 private:
  57   template <class T>
  58   inline void do_oop_work(T* p) {
  59     T o = oopDesc::load_heap_oop(p);
  60     if (! oopDesc::is_null(o)) {
  61       oop obj = oopDesc::decode_heap_oop_not_null(o);
  62       obj = ShenandoahBarrierSet::resolve_oop_static_not_null(obj);
  63       assert(oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj)),
  64              "expect forwarded oop");
  65       ShenandoahConcurrentMark::mark_and_push(obj, _heap, _queue);
  66     }
  67   }
  68 
  69 public:
  70   void do_oop(narrowOop* p) {
  71     do_oop_work(p);
  72   }
  73 
  74   inline void do_oop(oop* p) {
  75     do_oop_work(p);
  76   }
  77 
  78 };
  79 
  80 class SCMUpdateRefsClosure: public OopClosure {
  81 private:
  82   ShenandoahHeap* _heap;
  83 public:
  84 
  85   SCMUpdateRefsClosure() : _heap(ShenandoahHeap::heap()) {
  86   }
  87 
  88 private:
  89   template <class T>
  90   inline void do_oop_work(T* p) {
  91     T o = oopDesc::load_heap_oop(p);
  92     if (! oopDesc::is_null(o)) {
  93       oop obj = oopDesc::decode_heap_oop_not_null(o);
  94       _heap->update_oop_ref_not_null(p, obj);
  95     }
  96   }
  97 
  98 public:
  99   inline void do_oop(oop* p) {
 100     do_oop_work(p);
 101   }
 102 
 103   void do_oop(narrowOop* p) {
 104     do_oop_work(p);
 105   }
 106 };
 107 
 108 // Mark the object and add it to the queue to be scanned
 109 template <class T, bool CL>
 110 ShenandoahMarkObjsClosure<T, CL>::ShenandoahMarkObjsClosure(SCMObjToScanQueue* q, ReferenceProcessor* rp) :
 111   _heap((ShenandoahHeap*)(Universe::heap())),
 112   _queue(q),
 113   _mark_refs(T(q, rp)),
 114   _last_region_idx(0),
 115   _live_data(0)
 116 {
 117 }
 118 
 119 template <class T, bool CL>
 120 ShenandoahMarkObjsClosure<T, CL>::~ShenandoahMarkObjsClosure() {
 121   if (CL) {
 122     ShenandoahHeapRegion *r = _heap->regions()->get(_last_region_idx);
 123     r->increase_live_data(_live_data);
 124   }
 125 }
 126 
 127 ShenandoahMarkUpdateRefsClosure::ShenandoahMarkUpdateRefsClosure(SCMObjToScanQueue* q, ReferenceProcessor* rp) :
 128   MetadataAwareOopClosure(rp),
 129   _queue(q),
 130   _heap((ShenandoahHeap*) Universe::heap())
 131 {
 132 }
 133 
 134 ShenandoahMarkRefsClosure::ShenandoahMarkRefsClosure(SCMObjToScanQueue* q, ReferenceProcessor* rp) :
 135   MetadataAwareOopClosure(rp),
 136   _queue(q),
 137   _heap((ShenandoahHeap*) Universe::heap())
 138 {
 139 }
 140 
 141 class ShenandoahInitMarkRootsTask : public AbstractGangTask {
 142 private:
 143   ShenandoahRootProcessor* _rp;
 144   bool _process_refs;
 145 public:
 146   ShenandoahInitMarkRootsTask(ShenandoahRootProcessor* rp, bool process_refs) :
 147     AbstractGangTask("Shenandoah init mark roots task"),
 148     _rp(rp),
 149     _process_refs(process_refs) {
 150   }
 151 
 152   void work(uint worker_id) {
 153     ShenandoahHeap* heap = ShenandoahHeap::heap();
 154     SCMObjToScanQueue* q = heap->concurrentMark()->get_queue(worker_id);
 155     ShenandoahInitMarkRootsClosure mark_cl(q);
 156     CLDToOopClosure cldCl(&mark_cl);
 157     MarkingCodeBlobClosure blobsCl(&mark_cl, ! CodeBlobToOopClosure::FixRelocations);
 158 
 159     ResourceMark m;
 160     if (heap->concurrentMark()->unload_classes()) {
 161       _rp->process_strong_roots(&mark_cl, _process_refs ? NULL : &mark_cl, &cldCl, &blobsCl, worker_id);
 162     } else {
 163       _rp->process_all_roots(&mark_cl, _process_refs ? NULL : &mark_cl, &cldCl, ShenandoahConcurrentCodeRoots ? NULL : &blobsCl, worker_id);
 164     }
 165   }
 166 };
 167 
 168 class ShenandoahUpdateRootsTask : public AbstractGangTask {
 169 private:
 170   ShenandoahRootProcessor* _rp;
 171 public:
 172   ShenandoahUpdateRootsTask(ShenandoahRootProcessor* rp) :
 173     AbstractGangTask("Shenandoah update roots task"),
 174     _rp(rp) {
 175   }
 176 
 177   void work(uint worker_id) {
 178     ShenandoahHeap* heap = ShenandoahHeap::heap();
 179     SCMUpdateRefsClosure cl;
 180     CLDToOopClosure cldCl(&cl);
 181 
 182     _rp->process_all_roots(&cl, &cl, &cldCl, NULL, worker_id);
 183   }
 184 };
 185 
 186 class SCMConcurrentMarkingTask : public AbstractGangTask {
 187 private:
 188   ShenandoahConcurrentMark* _cm;
 189   ParallelTaskTerminator* _terminator;
 190   bool _update_refs;
 191 
 192 public:
 193   SCMConcurrentMarkingTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator, bool update_refs) :
 194     AbstractGangTask("Root Region Scan"), _cm(cm), _terminator(terminator), _update_refs(update_refs) {
 195   }
 196 
 197 
 198   void work(uint worker_id) {
 199 
 200     SCMObjToScanQueue* q = _cm->get_queue(worker_id);
 201     ReferenceProcessor* rp;
 202     if (_cm->process_references()) {
 203       rp = ShenandoahHeap::heap()->ref_processor();
 204     } else {
 205       rp = NULL;
 206     }
 207     if (ShenandoahConcurrentCodeRoots && _cm->claim_codecache()) {
 208       if (! _cm->unload_classes()) {
 209         ShenandoahMarkRefsClosure cl(q, rp);
 210         CodeBlobToOopClosure blobs(&cl, ! CodeBlobToOopClosure::FixRelocations);
 211         MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 212         CodeCache::blobs_do(&blobs);
 213       }
 214     }
 215     if (_update_refs) {
 216       ShenandoahMarkObjsClosure<ShenandoahMarkUpdateRefsClosure, true> cl(q, rp);
 217       _cm->concurrent_mark_loop(&cl, worker_id, q, _terminator);
 218     } else {
 219       ShenandoahMarkObjsClosure<ShenandoahMarkRefsClosure, true> cl(q, rp);
 220       _cm->concurrent_mark_loop(&cl, worker_id, q,  _terminator);
 221     }
 222     ShenandoahHeap* heap = ShenandoahHeap::heap();
 223   }
 224 };
 225 
 226 class SCMFinalMarkingTask : public AbstractGangTask {
 227 private:
 228   ShenandoahConcurrentMark* _cm;
 229   ParallelTaskTerminator* _terminator;
 230   bool _update_refs;
 231   bool _count_live;
 232 
 233 public:
 234   SCMFinalMarkingTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator, bool update_refs, bool count_live) :
 235     AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator), _update_refs(update_refs), _count_live(count_live) {
 236   }
 237 
 238   void work(uint worker_id) {
 239     ReferenceProcessor* rp;
 240     if (_cm->process_references()) {
 241       rp = ShenandoahHeap::heap()->ref_processor();
 242     } else {
 243       rp = NULL;
 244     }
 245     SCMObjToScanQueue* q = _cm->get_queue(worker_id);
 246 
 247     // Templates need constexprs, so we have to switch by the flags ourselves.
 248     if (_update_refs) {
 249       if (_count_live) {
 250         ShenandoahMarkObjsClosure<ShenandoahMarkUpdateRefsClosure, true> cl(q, rp);
 251         _cm->final_mark_loop(&cl, worker_id, q, _terminator);
 252       } else {
 253         ShenandoahMarkObjsClosure<ShenandoahMarkUpdateRefsClosure, false> cl(q, rp);
 254         _cm->final_mark_loop(&cl, worker_id, q, _terminator);
 255       }
 256     } else {
 257       if (_count_live) {
 258         ShenandoahMarkObjsClosure<ShenandoahMarkRefsClosure, true> cl(q, rp);
 259         _cm->final_mark_loop(&cl, worker_id, q, _terminator);
 260       } else {
 261         ShenandoahMarkObjsClosure<ShenandoahMarkRefsClosure, false> cl(q, rp);
 262         _cm->final_mark_loop(&cl, worker_id, q, _terminator);
 263       }
 264     }
 265   }
 266 };
 267 
 268 void ShenandoahConcurrentMark::mark_roots() {
 269   assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
 270 
 271   ShenandoahHeap* heap = ShenandoahHeap::heap();
 272 
 273   ClassLoaderDataGraph::clear_claimed_marks();
 274 
 275   ShenandoahRootProcessor root_proc(heap, _max_conc_worker_id, ShenandoahCollectorPolicy::scan_thread_roots);
 276   TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
 277   ShenandoahInitMarkRootsTask mark_roots(&root_proc, process_references());
 278   heap->conc_workers()->run_task(&mark_roots);
 279   if (ShenandoahConcurrentCodeRoots) {
 280     clear_claim_codecache();
 281   }
 282 }
 283 
 284 void ShenandoahConcurrentMark::init_mark_roots() {
 285   assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
 286 
 287   ShenandoahHeap* heap = ShenandoahHeap::heap();
 288 
 289   // Set up ref processing and class unloading.
 290   ShenandoahCollectorPolicy* policy = heap->shenandoahPolicy();
 291   set_process_references(policy->process_references());
 292   set_unload_classes(policy->unload_classes());
 293 
 294   mark_roots();
 295 }
 296 
 297 void ShenandoahConcurrentMark::update_roots() {
 298   ShenandoahHeap* heap = ShenandoahHeap::heap();
 299 
 300   ClassLoaderDataGraph::clear_claimed_marks();
 301 
 302   ShenandoahRootProcessor root_proc(heap, heap->max_parallel_workers(), ShenandoahCollectorPolicy::update_thread_roots);
 303   ShenandoahUpdateRootsTask update_roots(&root_proc);
 304   heap->workers()->run_task(&update_roots);
 305 
 306 }
 307 
 308 void ShenandoahConcurrentMark::final_update_roots() {
 309   assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
 310 
 311   COMPILER2_PRESENT(DerivedPointerTable::clear());
 312 
 313   update_roots();
 314 
 315   COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 316 }
 317 
 318 
 319 void ShenandoahConcurrentMark::initialize() {
 320   _max_conc_worker_id = MAX2((uint) ConcGCThreads, 1U);
 321   _task_queues = new SCMObjToScanQueueSet((int) _max_conc_worker_id);
 322 
 323   for (uint i = 0; i < _max_conc_worker_id; ++i) {
 324     SCMObjToScanQueue* task_queue = new SCMObjToScanQueue();
 325     task_queue->initialize();
 326     _task_queues->register_queue(i, task_queue);
 327   }
 328   _process_references = false;
 329   _unload_classes = false;
 330   _claimed_codecache = 0;
 331 
 332   JavaThread::satb_mark_queue_set().set_buffer_size(1014 /* G1SATBBufferSize */);
 333 }
 334 
 335 void ShenandoahConcurrentMark::mark_from_roots() {
 336 
 337   ShenandoahHeap* sh = (ShenandoahHeap *) Universe::heap();
 338 
 339   bool update_refs = sh->need_update_refs();
 340 
 341   sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::conc_mark);
 342 
 343   if (process_references()) {
 344     ReferenceProcessor* rp = sh->ref_processor();
 345     // enable ("weak") refs discovery
 346     rp->enable_discovery(true /*verify_no_refs*/);
 347     rp->setup_policy(sh->is_full_gc_in_progress()); // snapshot the soft ref policy to be used in this cycle
 348   }
 349 
 350   if (UseShenandoahOWST) {
 351     ShenandoahTaskTerminator terminator(_max_conc_worker_id, _task_queues);
 352     SCMConcurrentMarkingTask markingTask = SCMConcurrentMarkingTask(this, &terminator, update_refs);
 353     sh->conc_workers()->run_task(&markingTask);
 354   } else {
 355     ParallelTaskTerminator terminator(_max_conc_worker_id, _task_queues);
 356     SCMConcurrentMarkingTask markingTask = SCMConcurrentMarkingTask(this, &terminator, update_refs);
 357     sh->conc_workers()->run_task(&markingTask);
 358   }
 359 
 360   if (! sh->cancelled_concgc()) {
 361     TASKQUEUE_STATS_ONLY(print_taskqueue_stats());
 362   }
 363   TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
 364 
 365   sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::conc_mark);
 366 }
 367 
 368 class FinishDrainSATBBuffersTask : public AbstractGangTask {
 369 private:
 370   ShenandoahConcurrentMark* _cm;
 371   ParallelTaskTerminator* _terminator;
 372 public:
 373   FinishDrainSATBBuffersTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator) :
 374     AbstractGangTask("Finish draining SATB buffers"), _cm(cm), _terminator(terminator) {
 375   }
 376 
 377   void work(uint worker_id) {
 378     _cm->drain_satb_buffers(worker_id, true);
 379   }
 380 };
 381 
 382 void ShenandoahConcurrentMark::finish_mark_from_roots() {
 383 
 384   IsGCActiveMark is_active;
 385 
 386   ShenandoahHeap* sh = (ShenandoahHeap *) Universe::heap();
 387 
 388   TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
 389 
 390   sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::drain_satb);
 391   {
 392     StrongRootsScope scope(_max_conc_worker_id);
 393     if (UseShenandoahOWST) {
 394       ShenandoahTaskTerminator terminator(_max_conc_worker_id, _task_queues);
 395       // drain_satb_buffers(0, true);
 396       FinishDrainSATBBuffersTask drain_satb_buffers(this, &terminator);
 397       sh->conc_workers()->run_task(&drain_satb_buffers);
 398     } else {
 399       ParallelTaskTerminator terminator(_max_conc_worker_id, _task_queues);
 400       // drain_satb_buffers(0, true);
 401       FinishDrainSATBBuffersTask drain_satb_buffers(this, &terminator);
 402       sh->conc_workers()->run_task(&drain_satb_buffers);
 403     }
 404     sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::drain_satb);
 405   }
 406 
 407   shared_finish_mark_from_roots(/* full_gc = */ false);
 408 
 409   sh->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::update_roots);
 410   if (sh->need_update_refs()) {
 411     final_update_roots();
 412   }
 413   sh->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::update_roots);
 414 
 415   TASKQUEUE_STATS_ONLY(print_taskqueue_stats());
 416 
 417 #ifdef ASSERT
 418   verify_roots();
 419 
 420   if (ShenandoahDumpHeapAfterConcurrentMark) {
 421     sh->ensure_parsability(false);
 422     sh->print_all_refs("post-mark");
 423   }
 424 #endif
 425 }
 426 
 427 void ShenandoahConcurrentMark::shared_finish_mark_from_roots(bool full_gc) {
 428 
 429   ShenandoahHeap* sh = ShenandoahHeap::heap();
 430   ShenandoahCollectorPolicy* policy = sh->shenandoahPolicy();
 431 
 432   // Finally mark everything else we've got in our queues during the previous steps.
 433   {
 434     policy->record_phase_start(full_gc ?
 435                                ShenandoahCollectorPolicy::full_gc_mark_drain_queues :
 436                                ShenandoahCollectorPolicy::drain_queues);
 437     bool count_live = !(ShenandoahNoLivenessFullGC && full_gc); // we do not need liveness data for full GC
 438     if (UseShenandoahOWST) {
 439       ShenandoahTaskTerminator terminator(_max_conc_worker_id, _task_queues);
 440       SCMFinalMarkingTask markingTask = SCMFinalMarkingTask(this, &terminator, sh->need_update_refs(), count_live);
 441       sh->conc_workers()->run_task(&markingTask);
 442     } else {
 443       ParallelTaskTerminator terminator(_max_conc_worker_id, _task_queues);
 444       SCMFinalMarkingTask markingTask = SCMFinalMarkingTask(this, &terminator, sh->need_update_refs(), count_live);
 445       sh->conc_workers()->run_task(&markingTask);
 446     }
 447     policy->record_phase_end(full_gc ?
 448                              ShenandoahCollectorPolicy::full_gc_mark_drain_queues :
 449                              ShenandoahCollectorPolicy::drain_queues);
 450   }
 451 
 452 #ifdef ASSERT
 453   for (int i = 0; i < (int) _max_conc_worker_id; i++) {
 454     assert(_task_queues->queue(i)->is_empty(), "Should be empty");
 455   }
 456 #endif
 457 
 458   // When we're done marking everything, we process weak references.
 459   policy->record_phase_start(full_gc ?
 460                              ShenandoahCollectorPolicy::full_gc_mark_weakrefs :
 461                              ShenandoahCollectorPolicy::weakrefs);
 462   if (process_references()) {
 463     weak_refs_work();
 464   }
 465   policy->record_phase_end(full_gc ?
 466                            ShenandoahCollectorPolicy::full_gc_mark_weakrefs :
 467                            ShenandoahCollectorPolicy::weakrefs);
 468 
 469   // And finally finish class unloading
 470   policy->record_phase_start(full_gc ?
 471                              ShenandoahCollectorPolicy::full_gc_mark_class_unloading :
 472                              ShenandoahCollectorPolicy::class_unloading);
 473   if (unload_classes()) {
 474     ShenandoahForwardedIsAliveClosure is_alive;
 475     // Unload classes and purge SystemDictionary.
 476     bool purged_class = SystemDictionary::do_unloading(&is_alive, false);
 477     ParallelCleaningTask unlink_task(&is_alive, true, true, max_conc_worker_id(), purged_class);
 478     sh->conc_workers()->run_task(&unlink_task);
 479     ClassLoaderDataGraph::purge();
 480   }
 481   policy->record_phase_end(full_gc ?
 482                            ShenandoahCollectorPolicy::full_gc_mark_class_unloading :
 483                            ShenandoahCollectorPolicy::class_unloading);
 484 
 485 #ifdef ASSERT
 486   for (int i = 0; i < (int) _max_conc_worker_id; i++) {
 487     assert(_task_queues->queue(i)->is_empty(), "Should be empty");
 488   }
 489 #endif
 490 
 491 }
 492 
 493 #ifdef ASSERT
 494 template <class T>
 495 void ShenandoahVerifyRootsClosure1::do_oop_work(T* p) {
 496   T o = oopDesc::load_heap_oop(p);
 497   if (! oopDesc::is_null(o)) {
 498     oop obj = oopDesc::decode_heap_oop_not_null(o);
 499     if (! oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj))) {
 500       tty->print_cr("from-space marked: %s, to-space marked: %s, unload_classes: %s", BOOL_TO_STR(ShenandoahHeap::heap()->is_marked_current(obj)), BOOL_TO_STR(ShenandoahHeap::heap()->is_marked_current(ShenandoahBarrierSet::resolve_oop_static_not_null(obj))), BOOL_TO_STR(ShenandoahHeap::heap()->concurrentMark()->unload_classes()));
 501     }
 502     guarantee(oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj)), "oop must not be forwarded");
 503     guarantee(ShenandoahHeap::heap()->is_marked_current(obj), "oop must be marked");
 504   }
 505 }
 506 
 507 void ShenandoahVerifyRootsClosure1::do_oop(oop* p) {
 508   do_oop_work(p);
 509 }
 510 
 511 void ShenandoahVerifyRootsClosure1::do_oop(narrowOop* p) {
 512   do_oop_work(p);
 513 }
 514 
 515 void ShenandoahConcurrentMark::verify_roots() {
 516   ShenandoahVerifyRootsClosure1 cl;
 517   CodeBlobToOopClosure blobsCl(&cl, false);
 518   CLDToOopClosure cldCl(&cl);
 519   ClassLoaderDataGraph::clear_claimed_marks();
 520   ShenandoahRootProcessor rp(ShenandoahHeap::heap(), 1);
 521   rp.process_all_roots(&cl, &cl, &cldCl, &blobsCl, 0);
 522 
 523 }
 524 #endif
 525 
 526 class ShenandoahSATBThreadsClosure : public ThreadClosure {
 527   ShenandoahSATBBufferClosure* _satb_cl;
 528   int _thread_parity;
 529 
 530  public:
 531   ShenandoahSATBThreadsClosure(ShenandoahSATBBufferClosure* satb_cl) :
 532     _satb_cl(satb_cl),
 533     _thread_parity(Threads::thread_claim_parity()) {}
 534 
 535   void do_thread(Thread* thread) {
 536     if (thread->is_Java_thread()) {
 537       if (thread->claim_oops_do(true, _thread_parity)) {
 538         JavaThread* jt = (JavaThread*)thread;
 539         jt->satb_mark_queue().apply_closure_and_empty(_satb_cl);
 540       }
 541     } else if (thread->is_VM_thread()) {
 542       if (thread->claim_oops_do(true, _thread_parity)) {
 543         JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl);
 544       }
 545     }
 546   }
 547 };
 548 
 549 void ShenandoahConcurrentMark::drain_satb_buffers(uint worker_id, bool remark) {
 550   SCMObjToScanQueue* q = get_queue(worker_id);
 551   ShenandoahSATBBufferClosure cl(q);
 552 
 553   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
 554   while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
 555 
 556   if (remark) {
 557     ShenandoahSATBThreadsClosure tc(&cl);
 558     Threads::threads_do(&tc);
 559   }
 560 }
 561 
 562 #if TASKQUEUE_STATS
 563 void ShenandoahConcurrentMark::print_taskqueue_stats_hdr(outputStream* const st) {
 564   st->print_raw_cr("GC Task Stats");
 565   st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
 566   st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
 567 }
 568 
 569 void ShenandoahConcurrentMark::print_taskqueue_stats() const {
 570   if (!log_develop_is_enabled(Trace, gc, task, stats)) {
 571     return;
 572   }
 573   Log(gc, task, stats) log;
 574   ResourceMark rm;
 575   outputStream* st = log.trace_stream();
 576   print_taskqueue_stats_hdr(st);
 577 
 578   ShenandoahHeap* sh = (ShenandoahHeap*) Universe::heap();
 579   TaskQueueStats totals;
 580   const int n = sh->max_conc_workers();
 581   for (int i = 0; i < n; ++i) {
 582     st->print(INT32_FORMAT_W(3), i);
 583     _task_queues->queue(i)->stats.print(st);
 584     st->cr();
 585     totals += _task_queues->queue(i)->stats;
 586   }
 587   st->print("tot "); totals.print(st); st->cr();
 588   DEBUG_ONLY(totals.verify());
 589 
 590 }
 591 
 592 void ShenandoahConcurrentMark::reset_taskqueue_stats() {
 593   ShenandoahHeap* sh = (ShenandoahHeap*) Universe::heap();
 594   const int n = sh->max_conc_workers();
 595   for (int i = 0; i < n; ++i) {
 596     _task_queues->queue(i)->stats.reset();
 597   }
 598 }
 599 #endif // TASKQUEUE_STATS
 600 
 601 // Weak Reference Closures
 602 class ShenandoahCMDrainMarkingStackClosure: public VoidClosure {
 603   uint _worker_id;
 604   ParallelTaskTerminator* _terminator;
 605 
 606 public:
 607   ShenandoahCMDrainMarkingStackClosure(uint worker_id, ParallelTaskTerminator* t):
 608     _worker_id(worker_id),
 609     _terminator(t) {
 610   }
 611 
 612 
 613   void do_void() {
 614 
 615     ShenandoahHeap* sh = ShenandoahHeap::heap();
 616     ShenandoahConcurrentMark* scm = sh->concurrentMark();
 617     ReferenceProcessor* rp;
 618     if (scm->process_references()) {
 619       rp = ShenandoahHeap::heap()->ref_processor();
 620     } else {
 621       rp = NULL;
 622     }
 623     SCMObjToScanQueue* q = scm->get_queue(_worker_id);
 624     if (sh->need_update_refs()) {
 625       ShenandoahMarkObjsClosure<ShenandoahMarkUpdateRefsClosure, true> cl(q, rp);
 626       scm->final_mark_loop(&cl, _worker_id, q, _terminator);
 627     } else {
 628       ShenandoahMarkObjsClosure<ShenandoahMarkRefsClosure, true> cl(q, rp);
 629       scm->final_mark_loop(&cl, _worker_id, q, _terminator);
 630     }
 631   }
 632 };
 633 
 634 
 635 class ShenandoahCMKeepAliveClosure: public OopClosure {
 636   SCMObjToScanQueue* _queue;
 637   ShenandoahHeap* _sh;
 638 
 639 public:
 640   ShenandoahCMKeepAliveClosure(SCMObjToScanQueue* q) :
 641     _queue(q) {
 642     _sh = (ShenandoahHeap*) Universe::heap();
 643   }
 644 
 645 private:
 646   template <class T>
 647   inline void do_oop_work(T* p) {
 648 
 649     T o = oopDesc::load_heap_oop(p);
 650     if (! oopDesc::is_null(o)) {
 651       oop obj = oopDesc::decode_heap_oop_not_null(o);
 652       assert(oopDesc::unsafe_equals(obj, oopDesc::bs()->read_barrier(obj)), "only get updated oops in weak ref processing");
 653 
 654 #ifdef ASSERT
 655       if (log_is_enabled(Trace, gc, ref)) {
 656         ResourceMark rm;
 657         outputStream* out = Log(gc, ref)::trace_stream();
 658         out->print("\twe're looking at location "
 659                    "*"PTR_FORMAT" = "PTR_FORMAT,
 660                    p2i(p), p2i((void*) obj));
 661         obj->print_on(out);
 662       }
 663 #endif
 664       ShenandoahConcurrentMark::mark_and_push(obj, _sh, _queue);
 665     }
 666   }
 667 
 668 public:
 669   void do_oop(narrowOop* p) {
 670     do_oop_work(p);
 671   }
 672 
 673 
 674   void do_oop(oop* p) {
 675     do_oop_work(p);
 676   }
 677 
 678 };
 679 
 680 class ShenandoahCMKeepAliveUpdateClosure: public OopClosure {
 681   SCMObjToScanQueue* _queue;
 682   ShenandoahHeap* _sh;
 683 
 684 public:
 685   ShenandoahCMKeepAliveUpdateClosure(SCMObjToScanQueue* q) :
 686     _queue(q) {
 687     _sh = (ShenandoahHeap*) Universe::heap();
 688   }
 689 
 690 private:
 691   template <class T>
 692   inline void do_oop_work(T* p) {
 693     T o = oopDesc::load_heap_oop(p);
 694     if (! oopDesc::is_null(o)) {
 695       oop obj = oopDesc::decode_heap_oop_not_null(o);
 696       obj = _sh->update_oop_ref_not_null(p, obj);
 697       assert(oopDesc::unsafe_equals(obj, oopDesc::bs()->read_barrier(obj)), "only get updated oops in weak ref processing");
 698 #ifdef ASSERT
 699       if (log_is_enabled(Trace, gc, ref)) {
 700         ResourceMark rm;
 701         outputStream* out = Log(gc, ref)::trace_stream();
 702         out->print("\twe're looking at location "
 703                    "*"PTR_FORMAT" = "PTR_FORMAT,
 704                    p2i(p), p2i((void*) obj));
 705         obj->print_on(out);
 706       }
 707 #endif
 708       ShenandoahConcurrentMark::mark_and_push(obj, _sh, _queue);
 709     }
 710   }
 711 
 712 public:
 713   void do_oop(narrowOop* p) {
 714     do_oop_work(p);
 715   }
 716 
 717   void do_oop(oop* p) {
 718     do_oop_work(p);
 719   }
 720 
 721 };
 722 
 723 class ShenandoahRefProcTaskProxy : public AbstractGangTask {
 724 
 725 private:
 726   AbstractRefProcTaskExecutor::ProcessTask& _proc_task;
 727   ParallelTaskTerminator* _terminator;
 728 public:
 729 
 730   ShenandoahRefProcTaskProxy(AbstractRefProcTaskExecutor::ProcessTask& proc_task,
 731                              ParallelTaskTerminator* t) :
 732     AbstractGangTask("Process reference objects in parallel"),
 733     _proc_task(proc_task),
 734     _terminator(t) {
 735   }
 736 
 737   void work(uint worker_id) {
 738     ShenandoahHeap* heap = ShenandoahHeap::heap();
 739     ShenandoahForwardedIsAliveClosure is_alive;
 740     ShenandoahCMDrainMarkingStackClosure complete_gc(worker_id, _terminator);
 741     if (heap->need_update_refs()) {
 742       ShenandoahCMKeepAliveUpdateClosure keep_alive(heap->concurrentMark()->get_queue(worker_id));
 743       _proc_task.work(worker_id, is_alive, keep_alive, complete_gc);
 744     } else {
 745       ShenandoahCMKeepAliveClosure keep_alive(heap->concurrentMark()->get_queue(worker_id));
 746       _proc_task.work(worker_id, is_alive, keep_alive, complete_gc);
 747     }
 748   }
 749 };
 750 
 751 class ShenandoahRefEnqueueTaskProxy : public AbstractGangTask {
 752 
 753 private:
 754   AbstractRefProcTaskExecutor::EnqueueTask& _enqueue_task;
 755 
 756 public:
 757 
 758   ShenandoahRefEnqueueTaskProxy(AbstractRefProcTaskExecutor::EnqueueTask& enqueue_task) :
 759     AbstractGangTask("Enqueue reference objects in parallel"),
 760     _enqueue_task(enqueue_task) {
 761   }
 762 
 763   void work(uint worker_id) {
 764     _enqueue_task.work(worker_id);
 765   }
 766 };
 767 
 768 class ShenandoahRefProcTaskExecutor : public AbstractRefProcTaskExecutor {
 769 
 770 private:
 771   WorkGang* _workers;
 772 
 773 public:
 774 
 775   ShenandoahRefProcTaskExecutor() : _workers(ShenandoahHeap::heap()->conc_workers()) {
 776   }
 777 
 778   // Executes a task using worker threads.
 779   void execute(ProcessTask& task) {
 780     ShenandoahConcurrentMark* cm = ShenandoahHeap::heap()->concurrentMark();
 781     if (UseShenandoahOWST) {
 782       ShenandoahTaskTerminator terminator(cm->max_conc_worker_id(), cm->task_queues());
 783       ShenandoahRefProcTaskProxy proc_task_proxy(task, &terminator);
 784       _workers->run_task(&proc_task_proxy);
 785     } else {
 786       ParallelTaskTerminator terminator(cm->max_conc_worker_id(), cm->task_queues());
 787       ShenandoahRefProcTaskProxy proc_task_proxy(task, &terminator);
 788       _workers->run_task(&proc_task_proxy);
 789     }
 790   }
 791 
 792   void execute(EnqueueTask& task) {
 793     ShenandoahRefEnqueueTaskProxy enqueue_task_proxy(task);
 794     _workers->run_task(&enqueue_task_proxy);
 795   }
 796 };
 797 
 798 
 799 void ShenandoahConcurrentMark::weak_refs_work() {
 800   assert(process_references(), "sanity");
 801    ShenandoahHeap* sh = (ShenandoahHeap*) Universe::heap();
 802    ReferenceProcessor* rp = sh->ref_processor();
 803 
 804    // Setup collector policy for softref cleaning.
 805    bool clear_soft_refs = sh->collector_policy()->use_should_clear_all_soft_refs(true /* bogus arg*/);
 806    log_develop_debug(gc, ref)("clearing soft refs: %s", BOOL_TO_STR(clear_soft_refs));
 807    rp->setup_policy(clear_soft_refs);
 808 
 809    uint serial_worker_id = 0;
 810    ShenandoahForwardedIsAliveClosure is_alive;
 811    ParallelTaskTerminator terminator(1, task_queues());
 812    ShenandoahCMDrainMarkingStackClosure complete_gc(serial_worker_id, &terminator);
 813    ShenandoahRefProcTaskExecutor executor;
 814 
 815    log_develop_trace(gc, ref)("start processing references");
 816 
 817    if (sh->need_update_refs()) {
 818      ShenandoahCMKeepAliveUpdateClosure keep_alive(get_queue(serial_worker_id));
 819      rp->process_discovered_references(&is_alive, &keep_alive,
 820                                        &complete_gc, &executor,
 821                                        NULL);
 822    } else {
 823      ShenandoahCMKeepAliveClosure keep_alive(get_queue(serial_worker_id));
 824      rp->process_discovered_references(&is_alive, &keep_alive,
 825                                        &complete_gc, &executor,
 826                                        NULL);
 827    }
 828 
 829 #ifdef ASSERT
 830    for (int i = 0; i < (int) _max_conc_worker_id; i++) {
 831      assert(_task_queues->queue(i)->is_empty(), "Should be empty");
 832    }
 833 #endif
 834 
 835    log_develop_trace(gc, ref)("finished processing references");
 836    log_develop_trace(gc, ref)("start enqueuing references");
 837 
 838    rp->enqueue_discovered_references(&executor);
 839 
 840    log_develop_trace(gc, ref)("finished enqueueing references");
 841 
 842    rp->verify_no_references_recorded();
 843    assert(!rp->discovery_enabled(), "Post condition");
 844 
 845 }
 846 
 847 void ShenandoahConcurrentMark::cancel() {
 848   ShenandoahHeap* sh = ShenandoahHeap::heap();
 849 
 850   // Cancel weak-ref discovery.
 851   if (process_references()) {
 852     ReferenceProcessor* rp = sh->ref_processor();
 853     rp->abandon_partial_discovery();
 854     rp->disable_discovery();
 855   }
 856 
 857   // Clean up marking stacks.
 858   SCMObjToScanQueueSet* queues = task_queues();
 859   for (uint i = 0; i < _max_conc_worker_id; ++i) {
 860     clear_queue(queues->queue(i));
 861   }
 862 
 863   // Cancel SATB buffers.
 864   JavaThread::satb_mark_queue_set().abandon_partial_marking();
 865 }
 866 
 867 SCMObjToScanQueue* ShenandoahConcurrentMark::get_queue(uint worker_id) {
 868   assert (worker_id < _max_conc_worker_id, "valid worker id: %d", worker_id);
 869   return _task_queues->queue(worker_id);
 870 }
 871 
 872 void ShenandoahConcurrentMark::clear_queue(SCMObjToScanQueue *q) {
 873   q->set_empty();
 874   q->overflow_stack()->clear();
 875   q->clear_buffer();
 876 }
 877 
 878 template <class T, bool CL>
 879 void ShenandoahConcurrentMark::concurrent_mark_loop(ShenandoahMarkObjsClosure<T, CL>* cl,
 880                                                     uint worker_id,
 881                                                     SCMObjToScanQueue* q,
 882                                                     ParallelTaskTerminator* terminator) {
 883   ShenandoahHeap* heap = ShenandoahHeap::heap();
 884   int seed = 17;
 885   while (true) {
 886     if (heap->cancelled_concgc()) clear_queue(q);
 887     if (heap->cancelled_concgc() ||
 888         (!try_queue(q, cl) &&
 889          !try_draining_an_satb_buffer(q) &&
 890          !try_to_steal(worker_id, cl, &seed))
 891         ) {
 892       if (terminator->offer_termination()) break;
 893     }
 894   }
 895 }
 896 
 897 template <class T, bool CL>
 898 void ShenandoahConcurrentMark::final_mark_loop(ShenandoahMarkObjsClosure<T, CL>* cl,
 899                                                uint worker_id,
 900                                                SCMObjToScanQueue* q,
 901                                                ParallelTaskTerminator* terminator) {
 902   int seed = 17;
 903   while (true) {
 904     if (!try_queue(q, cl) &&
 905         !try_to_steal(worker_id, cl, &seed)) {
 906       if (terminator->offer_termination()) break;
 907     }
 908   }
 909 }
 910 
 911 void ShenandoahConcurrentMark::set_process_references(bool pr) {
 912   _process_references = pr;
 913 }
 914 
 915 bool ShenandoahConcurrentMark::process_references() const {
 916   return _process_references;
 917 }
 918 
 919 void ShenandoahConcurrentMark::set_unload_classes(bool uc) {
 920   _unload_classes = uc;
 921 }
 922 
 923 bool ShenandoahConcurrentMark::unload_classes() const {
 924   return _unload_classes;
 925 }
 926 
 927 bool ShenandoahConcurrentMark::claim_codecache() {
 928   assert(ShenandoahConcurrentCodeRoots, "must not be called otherwise");
 929   jbyte old = Atomic::cmpxchg(1, &_claimed_codecache, 0);
 930   return old == 0;
 931 }
 932 
 933 void ShenandoahConcurrentMark::clear_claim_codecache() {
 934   assert(ShenandoahConcurrentCodeRoots, "must not be called otherwise");
 935   _claimed_codecache = 0;
 936 }
 937 
 938 // Generate Shenandoah specialized oop_oop_iterate functions.
 939 SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_SHENANDOAH(ALL_KLASS_OOP_OOP_ITERATE_DEFN)