1 /*
2 * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
26 #define SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
27
28 #include "gc/shared/referencePolicy.hpp"
29 #include "gc/shared/referenceProcessorStats.hpp"
30 #include "memory/referenceType.hpp"
31 #include "oops/instanceRefKlass.hpp"
32
33 class GCTimer;
34
35 // ReferenceProcessor class encapsulates the per-"collector" processing
36 // of java.lang.Reference objects for GC. The interface is useful for supporting
37 // a generational abstraction, in particular when there are multiple
38 // generations that are being independently collected -- possibly
39 // concurrently and/or incrementally. Note, however, that the
40 // ReferenceProcessor class abstracts away from a generational setting
41 // by using only a heap interval (called "span" below), thus allowing
42 // its use in a straightforward manner in a general, non-generational
43 // setting.
44 //
45 // The basic idea is that each ReferenceProcessor object concerns
46 // itself with ("weak") reference processing in a specific "span"
47 // of the heap of interest to a specific collector. Currently,
48 // the span is a convex interval of the heap, but, efficiency
151 NOT_PRODUCT(
152 inline size_t processed() const { return _processed; }
153 inline size_t removed() const { return _removed; }
154 )
155
156 inline void move_to_next() {
157 if (_ref == _next) {
158 // End of the list.
159 _ref = NULL;
160 } else {
161 _ref = _next;
162 }
163 assert(_ref != _first_seen, "cyclic ref_list found");
164 NOT_PRODUCT(_processed++);
165 }
166 };
167
168 class ReferenceProcessor : public CHeapObj<mtGC> {
169
170 private:
171 size_t total_count(DiscoveredList lists[]);
172
173 protected:
174 // The SoftReference master timestamp clock
175 static jlong _soft_ref_timestamp_clock;
176
177 MemRegion _span; // (right-open) interval of heap
178 // subject to wkref discovery
179
180 bool _discovering_refs; // true when discovery enabled
181 bool _discovery_is_atomic; // if discovery is atomic wrt
182 // other collectors in configuration
183 bool _discovery_is_mt; // true if reference discovery is MT.
184
185 bool _enqueuing_is_done; // true if all weak references enqueued
186 bool _processing_is_mt; // true during phases when
187 // reference processing is MT.
188 uint _next_id; // round-robin mod _num_q counter in
189 // support of work distribution
190
191 // For collectors that do not keep GC liveness information
225 uint num_q() { return _num_q; }
226 uint max_num_q() { return _max_num_q; }
227 void set_active_mt_degree(uint v);
228
229 DiscoveredList* discovered_refs() { return _discovered_refs; }
230
231 ReferencePolicy* setup_policy(bool always_clear) {
232 _current_soft_ref_policy = always_clear ?
233 _always_clear_soft_ref_policy : _default_soft_ref_policy;
234 _current_soft_ref_policy->setup(); // snapshot the policy threshold
235 return _current_soft_ref_policy;
236 }
237
238 // Process references with a certain reachability level.
239 void process_discovered_reflist(DiscoveredList refs_lists[],
240 ReferencePolicy* policy,
241 bool clear_referent,
242 BoolObjectClosure* is_alive,
243 OopClosure* keep_alive,
244 VoidClosure* complete_gc,
245 AbstractRefProcTaskExecutor* task_executor);
246
247 void process_phaseJNI(BoolObjectClosure* is_alive,
248 OopClosure* keep_alive,
249 VoidClosure* complete_gc);
250
251 // Work methods used by the method process_discovered_reflist
252 // Phase1: keep alive all those referents that are otherwise
253 // dead but which must be kept alive by policy (and their closure).
254 void process_phase1(DiscoveredList& refs_list,
255 ReferencePolicy* policy,
256 BoolObjectClosure* is_alive,
257 OopClosure* keep_alive,
258 VoidClosure* complete_gc);
259 // Phase2: remove all those references whose referents are
260 // reachable.
261 inline void process_phase2(DiscoveredList& refs_list,
262 BoolObjectClosure* is_alive,
263 OopClosure* keep_alive,
264 VoidClosure* complete_gc) {
265 if (discovery_is_atomic()) {
293
294 // "Preclean" all the discovered reference lists
295 // by removing references with strongly reachable referents.
296 // The first argument is a predicate on an oop that indicates
297 // its (strong) reachability and the second is a closure that
298 // may be used to incrementalize or abort the precleaning process.
299 // The caller is responsible for taking care of potential
300 // interference with concurrent operations on these lists
301 // (or predicates involved) by other threads. Currently
302 // only used by the CMS collector.
303 void preclean_discovered_references(BoolObjectClosure* is_alive,
304 OopClosure* keep_alive,
305 VoidClosure* complete_gc,
306 YieldClosure* yield,
307 GCTimer* gc_timer);
308
309 // Returns the name of the discovered reference list
310 // occupying the i / _num_q slot.
311 const char* list_name(uint i);
312
313 void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor);
314
315 protected:
316 // "Preclean" the given discovered reference list
317 // by removing references with strongly reachable referents.
318 // Currently used in support of CMS only.
319 void preclean_discovered_reflist(DiscoveredList& refs_list,
320 BoolObjectClosure* is_alive,
321 OopClosure* keep_alive,
322 VoidClosure* complete_gc,
323 YieldClosure* yield);
324
325 // round-robin mod _num_q (not: _not_ mode _max_num_q)
326 uint next_id() {
327 uint id = _next_id;
328 assert(!_discovery_is_mt, "Round robin should only be used in serial discovery");
329 if (++_next_id == _num_q) {
330 _next_id = 0;
331 }
332 assert(_next_id < _num_q, "_next_id %u _num_q %u _max_num_q %u", _next_id, _num_q, _max_num_q);
333 return id;
403
404 // iterate over oops
405 void weak_oops_do(OopClosure* f); // weak roots
406
407 // Balance each of the discovered lists.
408 void balance_all_queues();
409 void verify_list(DiscoveredList& ref_list);
410
411 // Discover a Reference object, using appropriate discovery criteria
412 bool discover_reference(oop obj, ReferenceType rt);
413
414 // Has discovered references that need handling
415 bool has_discovered_references();
416
417 // Process references found during GC (called by the garbage collector)
418 ReferenceProcessorStats
419 process_discovered_references(BoolObjectClosure* is_alive,
420 OopClosure* keep_alive,
421 VoidClosure* complete_gc,
422 AbstractRefProcTaskExecutor* task_executor,
423 GCTimer *gc_timer);
424
425 // Enqueue references at end of GC (called by the garbage collector)
426 void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL);
427
428 // If a discovery is in process that is being superceded, abandon it: all
429 // the discovered lists will be empty, and all the objects on them will
430 // have NULL discovered fields. Must be called only at a safepoint.
431 void abandon_partial_discovery();
432
433 // debugging
434 void verify_no_references_recorded() PRODUCT_RETURN;
435 void verify_referent(oop obj) PRODUCT_RETURN;
436 };
437
438 // A utility class to disable reference discovery in
439 // the scope which contains it, for given ReferenceProcessor.
440 class NoRefDiscovery: StackObj {
441 private:
442 ReferenceProcessor* _rp;
443 bool _was_discovering_refs;
444 public:
445 NoRefDiscovery(ReferenceProcessor* rp) : _rp(rp) {
446 _was_discovering_refs = _rp->discovery_enabled();
447 if (_was_discovering_refs) {
448 _rp->disable_discovery();
449 }
450 }
451
452 ~NoRefDiscovery() {
569 class AbstractRefProcTaskExecutor {
570 public:
571
572 // Abstract tasks to execute.
573 class ProcessTask;
574 class EnqueueTask;
575
576 // Executes a task using worker threads.
577 virtual void execute(ProcessTask& task) = 0;
578 virtual void execute(EnqueueTask& task) = 0;
579
580 // Switch to single threaded mode.
581 virtual void set_single_threaded_mode() { };
582 };
583
584 // Abstract reference processing task to execute.
585 class AbstractRefProcTaskExecutor::ProcessTask {
586 protected:
587 ProcessTask(ReferenceProcessor& ref_processor,
588 DiscoveredList refs_lists[],
589 bool marks_oops_alive)
590 : _ref_processor(ref_processor),
591 _refs_lists(refs_lists),
592 _marks_oops_alive(marks_oops_alive)
593 { }
594
595 public:
596 virtual void work(unsigned int work_id, BoolObjectClosure& is_alive,
597 OopClosure& keep_alive,
598 VoidClosure& complete_gc) = 0;
599
600 // Returns true if a task marks some oops as alive.
601 bool marks_oops_alive() const
602 { return _marks_oops_alive; }
603
604 protected:
605 ReferenceProcessor& _ref_processor;
606 DiscoveredList* _refs_lists;
607 const bool _marks_oops_alive;
608 };
609
610 // Abstract reference processing task to execute.
611 class AbstractRefProcTaskExecutor::EnqueueTask {
612 protected:
613 EnqueueTask(ReferenceProcessor& ref_processor,
614 DiscoveredList refs_lists[],
615 int n_queues)
616 : _ref_processor(ref_processor),
617 _refs_lists(refs_lists),
618 _n_queues(n_queues)
619 { }
620
621 public:
622 virtual void work(unsigned int work_id) = 0;
623
624 protected:
625 ReferenceProcessor& _ref_processor;
626 DiscoveredList* _refs_lists;
627 int _n_queues;
628 };
629
630 #endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
|
1 /*
2 * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
26 #define SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
27
28 #include "gc/shared/referencePolicy.hpp"
29 #include "gc/shared/referenceProcessorPhaseTimes.hpp"
30 #include "gc/shared/referenceProcessorStats.hpp"
31 #include "memory/referenceType.hpp"
32 #include "oops/instanceRefKlass.hpp"
33
34 class GCTimer;
35
36 // ReferenceProcessor class encapsulates the per-"collector" processing
37 // of java.lang.Reference objects for GC. The interface is useful for supporting
38 // a generational abstraction, in particular when there are multiple
39 // generations that are being independently collected -- possibly
40 // concurrently and/or incrementally. Note, however, that the
41 // ReferenceProcessor class abstracts away from a generational setting
42 // by using only a heap interval (called "span" below), thus allowing
43 // its use in a straightforward manner in a general, non-generational
44 // setting.
45 //
46 // The basic idea is that each ReferenceProcessor object concerns
47 // itself with ("weak") reference processing in a specific "span"
48 // of the heap of interest to a specific collector. Currently,
49 // the span is a convex interval of the heap, but, efficiency
152 NOT_PRODUCT(
153 inline size_t processed() const { return _processed; }
154 inline size_t removed() const { return _removed; }
155 )
156
157 inline void move_to_next() {
158 if (_ref == _next) {
159 // End of the list.
160 _ref = NULL;
161 } else {
162 _ref = _next;
163 }
164 assert(_ref != _first_seen, "cyclic ref_list found");
165 NOT_PRODUCT(_processed++);
166 }
167 };
168
169 class ReferenceProcessor : public CHeapObj<mtGC> {
170
171 private:
172 size_t total_count(DiscoveredList lists[]) const;
173
174 protected:
175 // The SoftReference master timestamp clock
176 static jlong _soft_ref_timestamp_clock;
177
178 MemRegion _span; // (right-open) interval of heap
179 // subject to wkref discovery
180
181 bool _discovering_refs; // true when discovery enabled
182 bool _discovery_is_atomic; // if discovery is atomic wrt
183 // other collectors in configuration
184 bool _discovery_is_mt; // true if reference discovery is MT.
185
186 bool _enqueuing_is_done; // true if all weak references enqueued
187 bool _processing_is_mt; // true during phases when
188 // reference processing is MT.
189 uint _next_id; // round-robin mod _num_q counter in
190 // support of work distribution
191
192 // For collectors that do not keep GC liveness information
226 uint num_q() { return _num_q; }
227 uint max_num_q() { return _max_num_q; }
228 void set_active_mt_degree(uint v);
229
230 DiscoveredList* discovered_refs() { return _discovered_refs; }
231
232 ReferencePolicy* setup_policy(bool always_clear) {
233 _current_soft_ref_policy = always_clear ?
234 _always_clear_soft_ref_policy : _default_soft_ref_policy;
235 _current_soft_ref_policy->setup(); // snapshot the policy threshold
236 return _current_soft_ref_policy;
237 }
238
239 // Process references with a certain reachability level.
240 void process_discovered_reflist(DiscoveredList refs_lists[],
241 ReferencePolicy* policy,
242 bool clear_referent,
243 BoolObjectClosure* is_alive,
244 OopClosure* keep_alive,
245 VoidClosure* complete_gc,
246 AbstractRefProcTaskExecutor* task_executor,
247 ReferenceProcessorPhaseTimes* phase_times);
248
249 void process_phaseJNI(BoolObjectClosure* is_alive,
250 OopClosure* keep_alive,
251 VoidClosure* complete_gc);
252
253 // Work methods used by the method process_discovered_reflist
254 // Phase1: keep alive all those referents that are otherwise
255 // dead but which must be kept alive by policy (and their closure).
256 void process_phase1(DiscoveredList& refs_list,
257 ReferencePolicy* policy,
258 BoolObjectClosure* is_alive,
259 OopClosure* keep_alive,
260 VoidClosure* complete_gc);
261 // Phase2: remove all those references whose referents are
262 // reachable.
263 inline void process_phase2(DiscoveredList& refs_list,
264 BoolObjectClosure* is_alive,
265 OopClosure* keep_alive,
266 VoidClosure* complete_gc) {
267 if (discovery_is_atomic()) {
295
296 // "Preclean" all the discovered reference lists
297 // by removing references with strongly reachable referents.
298 // The first argument is a predicate on an oop that indicates
299 // its (strong) reachability and the second is a closure that
300 // may be used to incrementalize or abort the precleaning process.
301 // The caller is responsible for taking care of potential
302 // interference with concurrent operations on these lists
303 // (or predicates involved) by other threads. Currently
304 // only used by the CMS collector.
305 void preclean_discovered_references(BoolObjectClosure* is_alive,
306 OopClosure* keep_alive,
307 VoidClosure* complete_gc,
308 YieldClosure* yield,
309 GCTimer* gc_timer);
310
311 // Returns the name of the discovered reference list
312 // occupying the i / _num_q slot.
313 const char* list_name(uint i);
314
315 void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor,
316 ReferenceProcessorPhaseTimes* phase_times);
317
318 protected:
319 // "Preclean" the given discovered reference list
320 // by removing references with strongly reachable referents.
321 // Currently used in support of CMS only.
322 void preclean_discovered_reflist(DiscoveredList& refs_list,
323 BoolObjectClosure* is_alive,
324 OopClosure* keep_alive,
325 VoidClosure* complete_gc,
326 YieldClosure* yield);
327
328 // round-robin mod _num_q (not: _not_ mode _max_num_q)
329 uint next_id() {
330 uint id = _next_id;
331 assert(!_discovery_is_mt, "Round robin should only be used in serial discovery");
332 if (++_next_id == _num_q) {
333 _next_id = 0;
334 }
335 assert(_next_id < _num_q, "_next_id %u _num_q %u _max_num_q %u", _next_id, _num_q, _max_num_q);
336 return id;
406
407 // iterate over oops
408 void weak_oops_do(OopClosure* f); // weak roots
409
410 // Balance each of the discovered lists.
411 void balance_all_queues();
412 void verify_list(DiscoveredList& ref_list);
413
414 // Discover a Reference object, using appropriate discovery criteria
415 bool discover_reference(oop obj, ReferenceType rt);
416
417 // Has discovered references that need handling
418 bool has_discovered_references();
419
420 // Process references found during GC (called by the garbage collector)
421 ReferenceProcessorStats
422 process_discovered_references(BoolObjectClosure* is_alive,
423 OopClosure* keep_alive,
424 VoidClosure* complete_gc,
425 AbstractRefProcTaskExecutor* task_executor,
426 ReferenceProcessorPhaseTimes* phase_times);
427
428 // Enqueue references at end of GC (called by the garbage collector)
429 void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor,
430 ReferenceProcessorPhaseTimes* phase_times);
431
432 // If a discovery is in process that is being superceded, abandon it: all
433 // the discovered lists will be empty, and all the objects on them will
434 // have NULL discovered fields. Must be called only at a safepoint.
435 void abandon_partial_discovery();
436
437 size_t total_reference_count(ReferenceType rt) const;
438
439 // debugging
440 void verify_no_references_recorded() PRODUCT_RETURN;
441 void verify_referent(oop obj) PRODUCT_RETURN;
442 };
443
444 // A utility class to disable reference discovery in
445 // the scope which contains it, for given ReferenceProcessor.
446 class NoRefDiscovery: StackObj {
447 private:
448 ReferenceProcessor* _rp;
449 bool _was_discovering_refs;
450 public:
451 NoRefDiscovery(ReferenceProcessor* rp) : _rp(rp) {
452 _was_discovering_refs = _rp->discovery_enabled();
453 if (_was_discovering_refs) {
454 _rp->disable_discovery();
455 }
456 }
457
458 ~NoRefDiscovery() {
575 class AbstractRefProcTaskExecutor {
576 public:
577
578 // Abstract tasks to execute.
579 class ProcessTask;
580 class EnqueueTask;
581
582 // Executes a task using worker threads.
583 virtual void execute(ProcessTask& task) = 0;
584 virtual void execute(EnqueueTask& task) = 0;
585
586 // Switch to single threaded mode.
587 virtual void set_single_threaded_mode() { };
588 };
589
590 // Abstract reference processing task to execute.
591 class AbstractRefProcTaskExecutor::ProcessTask {
592 protected:
593 ProcessTask(ReferenceProcessor& ref_processor,
594 DiscoveredList refs_lists[],
595 bool marks_oops_alive,
596 ReferenceProcessorPhaseTimes* phase_times)
597 : _ref_processor(ref_processor),
598 _refs_lists(refs_lists),
599 _phase_times(phase_times),
600 _marks_oops_alive(marks_oops_alive)
601 { }
602
603 public:
604 virtual void work(unsigned int work_id, BoolObjectClosure& is_alive,
605 OopClosure& keep_alive,
606 VoidClosure& complete_gc) = 0;
607
608 // Returns true if a task marks some oops as alive.
609 bool marks_oops_alive() const
610 { return _marks_oops_alive; }
611
612 protected:
613 ReferenceProcessor& _ref_processor;
614 DiscoveredList* _refs_lists;
615 ReferenceProcessorPhaseTimes* _phase_times;
616 const bool _marks_oops_alive;
617 };
618
619 // Abstract reference processing task to execute.
620 class AbstractRefProcTaskExecutor::EnqueueTask {
621 protected:
622 EnqueueTask(ReferenceProcessor& ref_processor,
623 DiscoveredList refs_lists[],
624 int n_queues,
625 ReferenceProcessorPhaseTimes* phase_times)
626 : _ref_processor(ref_processor),
627 _refs_lists(refs_lists),
628 _n_queues(n_queues),
629 _phase_times(phase_times)
630 { }
631
632 public:
633 virtual void work(unsigned int work_id) = 0;
634
635 protected:
636 ReferenceProcessor& _ref_processor;
637 DiscoveredList* _refs_lists;
638 ReferenceProcessorPhaseTimes* _phase_times;
639 int _n_queues;
640 };
641
642 #endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
|