166 ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
167 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
168 ReferenceProcessor* rp;
169 if (heap->process_references()) {
170 rp = heap->ref_processor();
171 shenandoah_assert_rp_isalive_installed();
172 } else {
173 rp = NULL;
174 }
175
176 _cm->concurrent_scan_code_roots(worker_id, rp);
177 _cm->mark_loop(worker_id, _terminator, rp,
178 true, // cancellable
179 ShenandoahStringDedup::is_enabled()); // perform string dedup
180 }
181 };
182
183 class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure {
184 private:
185 ShenandoahSATBBufferClosure* _satb_cl;
186 MarkingCodeBlobClosure* _code_cl;
187 uintx _claim_token;
188
189 public:
190 ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl, MarkingCodeBlobClosure* code_cl) :
191 _satb_cl(satb_cl), _code_cl(code_cl),
192 _claim_token(Threads::thread_claim_token()) {}
193
194 void do_thread(Thread* thread) {
195 if (thread->claim_threads_do(true, _claim_token)) {
196 ShenandoahThreadLocalData::satb_mark_queue(thread).apply_closure_and_empty(_satb_cl);
197 if (_code_cl != NULL && thread->is_Java_thread()) {
198 // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
199 // however the liveness of oops reachable from nmethods have very complex lifecycles:
200 // * Alive if on the stack of an executing method
201 // * Weakly reachable otherwise
202 // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
203 // live by the SATB invariant but other oops recorded in nmethods may behave differently.
204 JavaThread* jt = (JavaThread*)thread;
205 jt->nmethods_do(_code_cl);
206 }
207 }
208 }
209 };
210
211 class ShenandoahFinalMarkingTask : public AbstractGangTask {
212 private:
213 ShenandoahConcurrentMark* _cm;
214 TaskTerminator* _terminator;
215 bool _dedup_string;
216
217 public:
218 ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
219 AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) {
220 }
221
222 void work(uint worker_id) {
223 ShenandoahHeap* heap = ShenandoahHeap::heap();
224
225 ShenandoahParallelWorkerSession worker_session(worker_id);
226 ReferenceProcessor* rp;
227 if (heap->process_references()) {
228 rp = heap->ref_processor();
229 shenandoah_assert_rp_isalive_installed();
230 } else {
231 rp = NULL;
232 }
233
234 // First drain remaining SATB buffers.
235 // Notice that this is not strictly necessary for mark-compact. But since
236 // it requires a StrongRootsScope around the task, we need to claim the
237 // threads, and performance-wise it doesn't really matter. Adds about 1ms to
238 // full-gc.
239 {
240 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
241
242 ShenandoahSATBBufferClosure cl(q);
243 SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
244 while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
245
246 if (heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
247 if (heap->has_forwarded_objects()) {
248 ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
249 MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
250 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, &blobsCl);
251 Threads::threads_do(&tc);
252 } else {
253 ShenandoahMarkRefsClosure mark_cl(q, rp);
254 MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
255 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, &blobsCl);
256 Threads::threads_do(&tc);
257 }
258 } else {
259 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, NULL);
260 Threads::threads_do(&tc);
261 }
262 }
263
264 if (heap->is_degenerated_gc_in_progress()) {
265 // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
266 // let's check here.
267 _cm->concurrent_scan_code_roots(worker_id, rp);
268 }
269
270 _cm->mark_loop(worker_id, _terminator, rp,
271 false, // not cancellable
272 _dedup_string);
273
274 assert(_cm->task_queues()->is_empty(), "Should be empty");
275 }
276 };
277
278 void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_phase) {
279 assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
|
166 ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
167 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
168 ReferenceProcessor* rp;
169 if (heap->process_references()) {
170 rp = heap->ref_processor();
171 shenandoah_assert_rp_isalive_installed();
172 } else {
173 rp = NULL;
174 }
175
176 _cm->concurrent_scan_code_roots(worker_id, rp);
177 _cm->mark_loop(worker_id, _terminator, rp,
178 true, // cancellable
179 ShenandoahStringDedup::is_enabled()); // perform string dedup
180 }
181 };
182
183 class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure {
184 private:
185 ShenandoahSATBBufferClosure* _satb_cl;
186 OopClosure* const _cl;
187 MarkingCodeBlobClosure* _code_cl;
188 uintx _claim_token;
189
190 public:
191 ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl, OopClosure* cl, MarkingCodeBlobClosure* code_cl) :
192 _satb_cl(satb_cl), _cl(cl), _code_cl(code_cl),
193 _claim_token(Threads::thread_claim_token()) {}
194
195 void do_thread(Thread* thread) {
196 if (thread->claim_threads_do(true, _claim_token)) {
197 ShenandoahThreadLocalData::satb_mark_queue(thread).apply_closure_and_empty(_satb_cl);
198 if (thread->is_Java_thread()) {
199 if (_cl != NULL) {
200 ResourceMark rm;
201 thread->oops_do(_cl, _code_cl);
202 } else if (_code_cl != NULL) {
203 // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
204 // however the liveness of oops reachable from nmethods have very complex lifecycles:
205 // * Alive if on the stack of an executing method
206 // * Weakly reachable otherwise
207 // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
208 // live by the SATB invariant but other oops recorded in nmethods may behave differently.
209 JavaThread* jt = (JavaThread*)thread;
210 jt->nmethods_do(_code_cl);
211 }
212 }
213 }
214 }
215 };
216
217 class ShenandoahFinalMarkingTask : public AbstractGangTask {
218 private:
219 ShenandoahConcurrentMark* _cm;
220 TaskTerminator* _terminator;
221 bool _dedup_string;
222
223 public:
224 ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
225 AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) {
226 }
227
228 void work(uint worker_id) {
229 ShenandoahHeap* heap = ShenandoahHeap::heap();
230
231 ShenandoahParallelWorkerSession worker_session(worker_id);
232 ReferenceProcessor* rp;
233 if (heap->process_references()) {
234 rp = heap->ref_processor();
235 shenandoah_assert_rp_isalive_installed();
236 } else {
237 rp = NULL;
238 }
239
240 // First drain remaining SATB buffers.
241 // Notice that this is not strictly necessary for mark-compact. But since
242 // it requires a StrongRootsScope around the task, we need to claim the
243 // threads, and performance-wise it doesn't really matter. Adds about 1ms to
244 // full-gc.
245 {
246 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
247
248 ShenandoahSATBBufferClosure cl(q);
249 SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
250 while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
251 bool do_nmethods = heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading();
252 if (heap->has_forwarded_objects()) {
253 ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
254 MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
255 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
256 ShenandoahStoreValEnqueueBarrier ? &resolve_mark_cl : NULL,
257 do_nmethods ? &blobsCl : NULL);
258 Threads::threads_do(&tc);
259 } else {
260 ShenandoahMarkRefsClosure mark_cl(q, rp);
261 MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
262 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
263 ShenandoahStoreValEnqueueBarrier ? &mark_cl : NULL,
264 do_nmethods ? &blobsCl : NULL);
265 Threads::threads_do(&tc);
266 }
267 }
268
269 if (heap->is_degenerated_gc_in_progress()) {
270 // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
271 // let's check here.
272 _cm->concurrent_scan_code_roots(worker_id, rp);
273 }
274
275 _cm->mark_loop(worker_id, _terminator, rp,
276 false, // not cancellable
277 _dedup_string);
278
279 assert(_cm->task_queues()->is_empty(), "Should be empty");
280 }
281 };
282
283 void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_phase) {
284 assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
|