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