< prev index next >

src/share/vm/gc_implementation/shenandoah/shenandoahConcurrentMark.cpp

Print this page
rev 11046 : Implement suspendible workers


  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 "precompiled.hpp"
  25 
  26 #include "classfile/symbolTable.hpp"
  27 #include "classfile/systemDictionary.hpp"
  28 #include "code/codeCache.hpp"
  29 
  30 #include "gc_implementation/shared/parallelCleaning.hpp"
  31 #include "gc_implementation/shenandoah/brooksPointer.hpp"
  32 #include "gc_implementation/shenandoah/shenandoahBarrierSet.inline.hpp"
  33 #include "gc_implementation/shenandoah/shenandoahConcurrentMark.inline.hpp"
  34 #include "gc_implementation/shenandoah/shenandoahOopClosures.inline.hpp"
  35 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
  36 #include "gc_implementation/shenandoah/shenandoahRootProcessor.hpp"

  37 #include "gc_implementation/shenandoah/shenandoahTaskqueue.hpp"
  38 #include "gc_implementation/shenandoah/shenandoahTaskqueue.inline.hpp"
  39 #include "gc_implementation/shenandoah/shenandoahWorkGroup.hpp"
  40 #include "gc_implementation/shenandoah/shenandoahUtils.hpp"
  41 #include "gc_implementation/shenandoah/shenandoah_specialized_oop_closures.hpp"
  42 
  43 #include "memory/referenceProcessor.hpp"
  44 #include "memory/iterator.inline.hpp"
  45 #include "memory/resourceArea.hpp"
  46 #include "oops/oop.inline.hpp"
  47 
  48 template<UpdateRefsMode UPDATE_REFS>
  49 class ShenandoahInitMarkRootsClosure : public OopClosure {
  50 private:
  51   ShenandoahObjToScanQueue* _queue;
  52   ShenandoahHeap* _heap;
  53   ShenandoahMarkingContext* const _mark_context;
  54 
  55   template <class T>
  56   inline void do_oop_nv(T* p) {


 178         DEBUG_ONLY(&assert_to_space)
 179         NOT_DEBUG(NULL);
 180     }
 181     _rp->process_all_roots(&cl, &cl, &cldCl, code_blobs, NULL, worker_id);
 182   }
 183 };
 184 
 185 class ShenandoahConcurrentMarkingTask : public AbstractGangTask {
 186 private:
 187   ShenandoahConcurrentMark* _cm;
 188   ParallelTaskTerminator* _terminator;
 189 
 190 public:
 191   ShenandoahConcurrentMarkingTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator) :
 192     AbstractGangTask("Root Region Scan"), _cm(cm), _terminator(terminator) {
 193   }
 194 
 195   void work(uint worker_id) {
 196     ShenandoahHeap* heap = ShenandoahHeap::heap();
 197     ShenandoahWorkerSession worker_session(worker_id);

 198     ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 199     ReferenceProcessor* rp;
 200     if (heap->process_references()) {
 201       rp = ShenandoahHeap::heap()->ref_processor();
 202       shenandoah_assert_rp_isalive_installed();
 203     } else {
 204       rp = NULL;
 205     }
 206 
 207     _cm->concurrent_scan_code_roots(worker_id, rp);
 208     _cm->mark_loop(worker_id, _terminator, rp,
 209                    true, // cancellable
 210                    ShenandoahStringDedup::is_enabled()); // perform string dedup
 211   }
 212 };
 213 
 214 class ShenandoahSATBThreadsClosure : public ThreadClosure {
 215   ShenandoahSATBBufferClosure* _satb_cl;
 216   int _thread_parity;
 217 


 898   int seed = 17;
 899   uintx stride = ShenandoahMarkLoopStride;
 900 
 901   ShenandoahHeap* heap = ShenandoahHeap::heap();
 902   ShenandoahObjToScanQueueSet* queues = task_queues();
 903   ShenandoahObjToScanQueue* q;
 904   ShenandoahMarkTask t;
 905 
 906   /*
 907    * Process outstanding queues, if any.
 908    *
 909    * There can be more queues than workers. To deal with the imbalance, we claim
 910    * extra queues first. Since marking can push new tasks into the queue associated
 911    * with this worker id, we come back to process this queue in the normal loop.
 912    */
 913   assert(queues->get_reserved() == heap->workers()->active_workers(),
 914     "Need to reserve proper number of queues");
 915 
 916   q = queues->claim_next();
 917   while (q != NULL) {
 918     if (CANCELLABLE && heap->cancelled_gc()) {
 919       ShenandoahCancelledTerminatorTerminator tt;

 920       while (!terminator->offer_termination(&tt));
 921       return;
 922     }
 923 
 924     for (uint i = 0; i < stride; i++) {
 925       if (q->pop(t)) {
 926         do_task<T>(q, cl, live_data, &t);
 927       } else {
 928         assert(q->is_empty(), "Must be empty");
 929         q = queues->claim_next();
 930         break;
 931       }
 932     }
 933   }
 934 
 935   q = get_queue(worker_id);
 936 
 937   ShenandoahSATBBufferClosure drain_satb(q);
 938   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
 939 
 940   /*
 941    * Normal marking loop:
 942    */
 943   while (true) {
 944     if (CANCELLABLE && heap->cancelled_gc()) {
 945       ShenandoahCancelledTerminatorTerminator tt;

 946       while (!terminator->offer_termination(&tt));
 947       return;
 948     }
 949 
 950     while (satb_mq_set.completed_buffers_num() > 0) {
 951       satb_mq_set.apply_closure_to_completed_buffer(&drain_satb);
 952     }
 953 
 954     uint work = 0;
 955     for (uint i = 0; i < stride; i++) {
 956       if (q->pop(t) ||
 957           queues->steal(worker_id, &seed, t)) {
 958         do_task<T>(q, cl, live_data, &t);
 959         work++;
 960       } else {
 961         break;
 962       }
 963     }
 964 
 965     if (work == 0) {
 966       // No work encountered in current stride, try to terminate.


 967       ShenandoahTerminationTimingsTracker term_tracker(worker_id);
 968       if (terminator->offer_termination()) return;
 969     }
 970   }
 971 }
 972 
 973 bool ShenandoahConcurrentMark::claim_codecache() {
 974   assert(ShenandoahConcurrentScanCodeRoots, "must not be called otherwise");
 975   return _claimed_codecache.try_set();
 976 }
 977 
 978 void ShenandoahConcurrentMark::clear_claim_codecache() {
 979   assert(ShenandoahConcurrentScanCodeRoots, "must not be called otherwise");
 980   _claimed_codecache.unset();
 981 }


  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 "precompiled.hpp"
  25 
  26 #include "classfile/symbolTable.hpp"
  27 #include "classfile/systemDictionary.hpp"
  28 #include "code/codeCache.hpp"
  29 
  30 #include "gc_implementation/shared/parallelCleaning.hpp"
  31 #include "gc_implementation/shenandoah/brooksPointer.hpp"
  32 #include "gc_implementation/shenandoah/shenandoahBarrierSet.inline.hpp"
  33 #include "gc_implementation/shenandoah/shenandoahConcurrentMark.inline.hpp"
  34 #include "gc_implementation/shenandoah/shenandoahOopClosures.inline.hpp"
  35 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
  36 #include "gc_implementation/shenandoah/shenandoahRootProcessor.hpp"
  37 #include "gc_implementation/shenandoah/shenandoahSuspendibleThreadSet.hpp"
  38 #include "gc_implementation/shenandoah/shenandoahTaskqueue.hpp"
  39 #include "gc_implementation/shenandoah/shenandoahTaskqueue.inline.hpp"
  40 #include "gc_implementation/shenandoah/shenandoahWorkGroup.hpp"
  41 #include "gc_implementation/shenandoah/shenandoahUtils.hpp"
  42 #include "gc_implementation/shenandoah/shenandoah_specialized_oop_closures.hpp"
  43 
  44 #include "memory/referenceProcessor.hpp"
  45 #include "memory/iterator.inline.hpp"
  46 #include "memory/resourceArea.hpp"
  47 #include "oops/oop.inline.hpp"
  48 
  49 template<UpdateRefsMode UPDATE_REFS>
  50 class ShenandoahInitMarkRootsClosure : public OopClosure {
  51 private:
  52   ShenandoahObjToScanQueue* _queue;
  53   ShenandoahHeap* _heap;
  54   ShenandoahMarkingContext* const _mark_context;
  55 
  56   template <class T>
  57   inline void do_oop_nv(T* p) {


 179         DEBUG_ONLY(&assert_to_space)
 180         NOT_DEBUG(NULL);
 181     }
 182     _rp->process_all_roots(&cl, &cl, &cldCl, code_blobs, NULL, worker_id);
 183   }
 184 };
 185 
 186 class ShenandoahConcurrentMarkingTask : public AbstractGangTask {
 187 private:
 188   ShenandoahConcurrentMark* _cm;
 189   ParallelTaskTerminator* _terminator;
 190 
 191 public:
 192   ShenandoahConcurrentMarkingTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator) :
 193     AbstractGangTask("Root Region Scan"), _cm(cm), _terminator(terminator) {
 194   }
 195 
 196   void work(uint worker_id) {
 197     ShenandoahHeap* heap = ShenandoahHeap::heap();
 198     ShenandoahWorkerSession worker_session(worker_id);
 199     ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
 200     ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 201     ReferenceProcessor* rp;
 202     if (heap->process_references()) {
 203       rp = ShenandoahHeap::heap()->ref_processor();
 204       shenandoah_assert_rp_isalive_installed();
 205     } else {
 206       rp = NULL;
 207     }
 208 
 209     _cm->concurrent_scan_code_roots(worker_id, rp);
 210     _cm->mark_loop(worker_id, _terminator, rp,
 211                    true, // cancellable
 212                    ShenandoahStringDedup::is_enabled()); // perform string dedup
 213   }
 214 };
 215 
 216 class ShenandoahSATBThreadsClosure : public ThreadClosure {
 217   ShenandoahSATBBufferClosure* _satb_cl;
 218   int _thread_parity;
 219 


 900   int seed = 17;
 901   uintx stride = ShenandoahMarkLoopStride;
 902 
 903   ShenandoahHeap* heap = ShenandoahHeap::heap();
 904   ShenandoahObjToScanQueueSet* queues = task_queues();
 905   ShenandoahObjToScanQueue* q;
 906   ShenandoahMarkTask t;
 907 
 908   /*
 909    * Process outstanding queues, if any.
 910    *
 911    * There can be more queues than workers. To deal with the imbalance, we claim
 912    * extra queues first. Since marking can push new tasks into the queue associated
 913    * with this worker id, we come back to process this queue in the normal loop.
 914    */
 915   assert(queues->get_reserved() == heap->workers()->active_workers(),
 916     "Need to reserve proper number of queues");
 917 
 918   q = queues->claim_next();
 919   while (q != NULL) {
 920     if (CANCELLABLE && heap->check_cancelled_gc_and_yield()) {
 921       ShenandoahCancelledTerminatorTerminator tt;
 922       ShenandoahSuspendibleThreadSetLeaver stsl(ShenandoahSuspendibleWorkers);
 923       while (!terminator->offer_termination(&tt));
 924       return;
 925     }
 926 
 927     for (uint i = 0; i < stride; i++) {
 928       if (q->pop(t)) {
 929         do_task<T>(q, cl, live_data, &t);
 930       } else {
 931         assert(q->is_empty(), "Must be empty");
 932         q = queues->claim_next();
 933         break;
 934       }
 935     }
 936   }
 937 
 938   q = get_queue(worker_id);
 939 
 940   ShenandoahSATBBufferClosure drain_satb(q);
 941   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
 942 
 943   /*
 944    * Normal marking loop:
 945    */
 946   while (true) {
 947     if (CANCELLABLE && heap->check_cancelled_gc_and_yield()) {
 948       ShenandoahCancelledTerminatorTerminator tt;
 949       ShenandoahSuspendibleThreadSetLeaver stsl(ShenandoahSuspendibleWorkers);
 950       while (!terminator->offer_termination(&tt));
 951       return;
 952     }
 953 
 954     while (satb_mq_set.completed_buffers_num() > 0) {
 955       satb_mq_set.apply_closure_to_completed_buffer(&drain_satb);
 956     }
 957 
 958     uint work = 0;
 959     for (uint i = 0; i < stride; i++) {
 960       if (q->pop(t) ||
 961           queues->steal(worker_id, &seed, t)) {
 962         do_task<T>(q, cl, live_data, &t);
 963         work++;
 964       } else {
 965         break;
 966       }
 967     }
 968 
 969     if (work == 0) {
 970       // No work encountered in current stride, try to terminate.
 971       // Need to leave the STS here otherwise it might block safepoints.
 972       ShenandoahSuspendibleThreadSetLeaver stsl(CANCELLABLE && ShenandoahSuspendibleWorkers);
 973       ShenandoahTerminationTimingsTracker term_tracker(worker_id);
 974       if (terminator->offer_termination()) return;
 975     }
 976   }
 977 }
 978 
 979 bool ShenandoahConcurrentMark::claim_codecache() {
 980   assert(ShenandoahConcurrentScanCodeRoots, "must not be called otherwise");
 981   return _claimed_codecache.try_set();
 982 }
 983 
 984 void ShenandoahConcurrentMark::clear_claim_codecache() {
 985   assert(ShenandoahConcurrentScanCodeRoots, "must not be called otherwise");
 986   _claimed_codecache.unset();
 987 }
< prev index next >