1 /* 2 * Copyright (c) 2001, 2011, 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_MEMORY_REFERENCEPROCESSOR_HPP 26 #define SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP 27 28 #include "memory/referencePolicy.hpp" 29 #include "oops/instanceRefKlass.hpp" 30 31 // ReferenceProcessor class encapsulates the per-"collector" processing 32 // of java.lang.Reference objects for GC. The interface is useful for supporting 33 // a generational abstraction, in particular when there are multiple 34 // generations that are being independently collected -- possibly 35 // concurrently and/or incrementally. Note, however, that the 36 // ReferenceProcessor class abstracts away from a generational setting 37 // by using only a heap interval (called "span" below), thus allowing 38 // its use in a straightforward manner in a general, non-generational 39 // setting. 40 // 41 // The basic idea is that each ReferenceProcessor object concerns 42 // itself with ("weak") reference processing in a specific "span" 43 // of the heap of interest to a specific collector. Currently, 44 // the span is a convex interval of the heap, but, efficiency 45 // apart, there seems to be no reason it couldn't be extended 46 // (with appropriate modifications) to any "non-convex interval". 47 48 // forward references 49 class ReferencePolicy; 50 class AbstractRefProcTaskExecutor; 51 class DiscoveredList; 52 53 class ReferenceProcessor : public CHeapObj { 54 protected: 55 // End of list marker 56 static oop _sentinelRef; 57 MemRegion _span; // (right-open) interval of heap 58 // subject to wkref discovery 59 bool _discovering_refs; // true when discovery enabled 60 bool _discovery_is_atomic; // if discovery is atomic wrt 61 // other collectors in configuration 62 bool _discovery_is_mt; // true if reference discovery is MT. 63 // If true, setting "next" field of a discovered refs list requires 64 // write barrier(s). (Must be true if used in a collector in which 65 // elements of a discovered list may be moved during discovery: for 66 // example, a collector like Garbage-First that moves objects during a 67 // long-term concurrent marking phase that does weak reference 68 // discovery.) 69 bool _discovered_list_needs_barrier; 70 BarrierSet* _bs; // Cached copy of BarrierSet. 71 bool _enqueuing_is_done; // true if all weak references enqueued 72 bool _processing_is_mt; // true during phases when 73 // reference processing is MT. 74 int _next_id; // round-robin mod _num_q counter in 75 // support of work distribution 76 77 // For collectors that do not keep GC marking information 78 // in the object header, this field holds a closure that 79 // helps the reference processor determine the reachability 80 // of an oop (the field is currently initialized to NULL for 81 // all collectors but the CMS collector). 82 BoolObjectClosure* _is_alive_non_header; 83 84 // Soft ref clearing policies 85 // . the default policy 86 static ReferencePolicy* _default_soft_ref_policy; 87 // . the "clear all" policy 88 static ReferencePolicy* _always_clear_soft_ref_policy; 89 // . the current policy below is either one of the above 90 ReferencePolicy* _current_soft_ref_policy; 91 92 // The discovered ref lists themselves 93 94 // The active MT'ness degree of the queues below 95 int _num_q; 96 // The maximum MT'ness degree of the queues below 97 int _max_num_q; 98 // Arrays of lists of oops, one per thread 99 DiscoveredList* _discoveredSoftRefs; 100 DiscoveredList* _discoveredWeakRefs; 101 DiscoveredList* _discoveredFinalRefs; 102 DiscoveredList* _discoveredPhantomRefs; 103 104 public: 105 int num_q() { return _num_q; } 106 int max_num_q() { return _max_num_q; } 107 void set_active_mt_degree(int v) { _num_q = v; } 108 DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } 109 static oop sentinel_ref() { return _sentinelRef; } 110 static oop* adr_sentinel_ref() { return &_sentinelRef; } 111 ReferencePolicy* setup_policy(bool always_clear) { 112 _current_soft_ref_policy = always_clear ? 113 _always_clear_soft_ref_policy : _default_soft_ref_policy; 114 _current_soft_ref_policy->setup(); // snapshot the policy threshold 115 return _current_soft_ref_policy; 116 } 117 118 public: 119 // Process references with a certain reachability level. 120 void process_discovered_reflist(DiscoveredList refs_lists[], 121 ReferencePolicy* policy, 122 bool clear_referent, 123 BoolObjectClosure* is_alive, 124 OopClosure* keep_alive, 125 VoidClosure* complete_gc, 126 AbstractRefProcTaskExecutor* task_executor); 127 128 void process_phaseJNI(BoolObjectClosure* is_alive, 129 OopClosure* keep_alive, 130 VoidClosure* complete_gc); 131 132 // Work methods used by the method process_discovered_reflist 133 // Phase1: keep alive all those referents that are otherwise 134 // dead but which must be kept alive by policy (and their closure). 135 void process_phase1(DiscoveredList& refs_list, 136 ReferencePolicy* policy, 137 BoolObjectClosure* is_alive, 138 OopClosure* keep_alive, 139 VoidClosure* complete_gc); 140 // Phase2: remove all those references whose referents are 141 // reachable. 142 inline void process_phase2(DiscoveredList& refs_list, 143 BoolObjectClosure* is_alive, 144 OopClosure* keep_alive, 145 VoidClosure* complete_gc) { 146 if (discovery_is_atomic()) { 147 // complete_gc is ignored in this case for this phase 148 pp2_work(refs_list, is_alive, keep_alive); 149 } else { 150 assert(complete_gc != NULL, "Error"); 151 pp2_work_concurrent_discovery(refs_list, is_alive, 152 keep_alive, complete_gc); 153 } 154 } 155 // Work methods in support of process_phase2 156 void pp2_work(DiscoveredList& refs_list, 157 BoolObjectClosure* is_alive, 158 OopClosure* keep_alive); 159 void pp2_work_concurrent_discovery( 160 DiscoveredList& refs_list, 161 BoolObjectClosure* is_alive, 162 OopClosure* keep_alive, 163 VoidClosure* complete_gc); 164 // Phase3: process the referents by either clearing them 165 // or keeping them alive (and their closure) 166 void process_phase3(DiscoveredList& refs_list, 167 bool clear_referent, 168 BoolObjectClosure* is_alive, 169 OopClosure* keep_alive, 170 VoidClosure* complete_gc); 171 172 // Enqueue references with a certain reachability level 173 void enqueue_discovered_reflist(DiscoveredList& refs_list, HeapWord* pending_list_addr); 174 175 // "Preclean" all the discovered reference lists 176 // by removing references with strongly reachable referents. 177 // The first argument is a predicate on an oop that indicates 178 // its (strong) reachability and the second is a closure that 179 // may be used to incrementalize or abort the precleaning process. 180 // The caller is responsible for taking care of potential 181 // interference with concurrent operations on these lists 182 // (or predicates involved) by other threads. Currently 183 // only used by the CMS collector. should_unload_classes is 184 // used to aid assertion checking when classes are collected. 185 void preclean_discovered_references(BoolObjectClosure* is_alive, 186 OopClosure* keep_alive, 187 VoidClosure* complete_gc, 188 YieldClosure* yield, 189 bool should_unload_classes); 190 191 // Delete entries in the discovered lists that have 192 // either a null referent or are not active. Such 193 // Reference objects can result from the clearing 194 // or enqueueing of Reference objects concurrent 195 // with their discovery by a (concurrent) collector. 196 // For a definition of "active" see java.lang.ref.Reference; 197 // Refs are born active, become inactive when enqueued, 198 // and never become active again. The state of being 199 // active is encoded as follows: A Ref is active 200 // if and only if its "next" field is NULL. 201 void clean_up_discovered_references(); 202 void clean_up_discovered_reflist(DiscoveredList& refs_list); 203 204 // Returns the name of the discovered reference list 205 // occupying the i / _num_q slot. 206 const char* list_name(int i); 207 208 void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); 209 210 protected: 211 // "Preclean" the given discovered reference list 212 // by removing references with strongly reachable referents. 213 // Currently used in support of CMS only. 214 void preclean_discovered_reflist(DiscoveredList& refs_list, 215 BoolObjectClosure* is_alive, 216 OopClosure* keep_alive, 217 VoidClosure* complete_gc, 218 YieldClosure* yield); 219 220 // round-robin mod _num_q (not: _not_ mode _max_num_q) 221 int next_id() { 222 int id = _next_id; 223 if (++_next_id == _num_q) { 224 _next_id = 0; 225 } 226 return id; 227 } 228 DiscoveredList* get_discovered_list(ReferenceType rt); 229 inline void add_to_discovered_list_mt(DiscoveredList& refs_list, oop obj, 230 HeapWord* discovered_addr); 231 void verify_ok_to_handle_reflists() PRODUCT_RETURN; 232 233 void abandon_partial_discovered_list(DiscoveredList& refs_list); 234 235 // Calculate the number of jni handles. 236 unsigned int count_jni_refs(); 237 238 // Balances reference queues. 239 void balance_queues(DiscoveredList ref_lists[]); 240 241 // Update (advance) the soft ref master clock field. 242 void update_soft_ref_master_clock(); 243 244 public: 245 // constructor 246 ReferenceProcessor(): 247 _span((HeapWord*)NULL, (HeapWord*)NULL), 248 _discoveredSoftRefs(NULL), _discoveredWeakRefs(NULL), 249 _discoveredFinalRefs(NULL), _discoveredPhantomRefs(NULL), 250 _discovering_refs(false), 251 _discovery_is_atomic(true), 252 _enqueuing_is_done(false), 253 _discovery_is_mt(false), 254 _discovered_list_needs_barrier(false), 255 _bs(NULL), 256 _is_alive_non_header(NULL), 257 _num_q(0), 258 _max_num_q(0), 259 _processing_is_mt(false), 260 _next_id(0) 261 { } 262 263 // Default parameters give you a vanilla reference processor. 264 ReferenceProcessor(MemRegion span, 265 bool mt_processing = false, int mt_processing_degree = 1, 266 bool mt_discovery = false, int mt_discovery_degree = 1, 267 bool atomic_discovery = true, 268 BoolObjectClosure* is_alive_non_header = NULL, 269 bool discovered_list_needs_barrier = false); 270 271 // RefDiscoveryPolicy values 272 enum DiscoveryPolicy { 273 ReferenceBasedDiscovery = 0, 274 ReferentBasedDiscovery = 1, 275 DiscoveryPolicyMin = ReferenceBasedDiscovery, 276 DiscoveryPolicyMax = ReferentBasedDiscovery 277 }; 278 279 static void init_statics(); 280 281 public: 282 // get and set "is_alive_non_header" field 283 BoolObjectClosure* is_alive_non_header() { 284 return _is_alive_non_header; 285 } 286 void set_is_alive_non_header(BoolObjectClosure* is_alive_non_header) { 287 _is_alive_non_header = is_alive_non_header; 288 } 289 290 // get and set span 291 MemRegion span() { return _span; } 292 void set_span(MemRegion span) { _span = span; } 293 294 // start and stop weak ref discovery 295 void enable_discovery() { _discovering_refs = true; } 296 void disable_discovery() { _discovering_refs = false; } 297 bool discovery_enabled() { return _discovering_refs; } 298 299 // whether discovery is atomic wrt other collectors 300 bool discovery_is_atomic() const { return _discovery_is_atomic; } 301 void set_atomic_discovery(bool atomic) { _discovery_is_atomic = atomic; } 302 303 // whether discovery is done by multiple threads same-old-timeously 304 bool discovery_is_mt() const { return _discovery_is_mt; } 305 void set_mt_discovery(bool mt) { _discovery_is_mt = mt; } 306 307 // Whether we are in a phase when _processing_ is MT. 308 bool processing_is_mt() const { return _processing_is_mt; } 309 void set_mt_processing(bool mt) { _processing_is_mt = mt; } 310 311 // whether all enqueuing of weak references is complete 312 bool enqueuing_is_done() { return _enqueuing_is_done; } 313 void set_enqueuing_is_done(bool v) { _enqueuing_is_done = v; } 314 315 // iterate over oops 316 void weak_oops_do(OopClosure* f); // weak roots 317 static void oops_do(OopClosure* f); // strong root(s) 318 319 // Balance each of the discovered lists. 320 void balance_all_queues(); 321 322 // Discover a Reference object, using appropriate discovery criteria 323 bool discover_reference(oop obj, ReferenceType rt); 324 325 // Process references found during GC (called by the garbage collector) 326 void process_discovered_references(BoolObjectClosure* is_alive, 327 OopClosure* keep_alive, 328 VoidClosure* complete_gc, 329 AbstractRefProcTaskExecutor* task_executor); 330 331 public: 332 // Enqueue references at end of GC (called by the garbage collector) 333 bool enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL); 334 335 // If a discovery is in process that is being superceded, abandon it: all 336 // the discovered lists will be empty, and all the objects on them will 337 // have NULL discovered fields. Must be called only at a safepoint. 338 void abandon_partial_discovery(); 339 340 // debugging 341 void verify_no_references_recorded() PRODUCT_RETURN; 342 void verify_referent(oop obj) PRODUCT_RETURN; 343 static void verify(); 344 345 // clear the discovered lists (unlinking each entry). 346 void clear_discovered_references() PRODUCT_RETURN; 347 }; 348 349 // A utility class to disable reference discovery in 350 // the scope which contains it, for given ReferenceProcessor. 351 class NoRefDiscovery: StackObj { 352 private: 353 ReferenceProcessor* _rp; 354 bool _was_discovering_refs; 355 public: 356 NoRefDiscovery(ReferenceProcessor* rp) : _rp(rp) { 357 _was_discovering_refs = _rp->discovery_enabled(); 358 if (_was_discovering_refs) { 359 _rp->disable_discovery(); 360 } 361 } 362 363 ~NoRefDiscovery() { 364 if (_was_discovering_refs) { 365 _rp->enable_discovery(); 366 } 367 } 368 }; 369 370 371 // A utility class to temporarily mutate the span of the 372 // given ReferenceProcessor in the scope that contains it. 373 class ReferenceProcessorSpanMutator: StackObj { 374 private: 375 ReferenceProcessor* _rp; 376 MemRegion _saved_span; 377 378 public: 379 ReferenceProcessorSpanMutator(ReferenceProcessor* rp, 380 MemRegion span): 381 _rp(rp) { 382 _saved_span = _rp->span(); 383 _rp->set_span(span); 384 } 385 386 ~ReferenceProcessorSpanMutator() { 387 _rp->set_span(_saved_span); 388 } 389 }; 390 391 // A utility class to temporarily change the MT'ness of 392 // reference discovery for the given ReferenceProcessor 393 // in the scope that contains it. 394 class ReferenceProcessorMTDiscoveryMutator: StackObj { 395 private: 396 ReferenceProcessor* _rp; 397 bool _saved_mt; 398 399 public: 400 ReferenceProcessorMTDiscoveryMutator(ReferenceProcessor* rp, 401 bool mt): 402 _rp(rp) { 403 _saved_mt = _rp->discovery_is_mt(); 404 _rp->set_mt_discovery(mt); 405 } 406 407 ~ReferenceProcessorMTDiscoveryMutator() { 408 _rp->set_mt_discovery(_saved_mt); 409 } 410 }; 411 412 413 // A utility class to temporarily change the disposition 414 // of the "is_alive_non_header" closure field of the 415 // given ReferenceProcessor in the scope that contains it. 416 class ReferenceProcessorIsAliveMutator: StackObj { 417 private: 418 ReferenceProcessor* _rp; 419 BoolObjectClosure* _saved_cl; 420 421 public: 422 ReferenceProcessorIsAliveMutator(ReferenceProcessor* rp, 423 BoolObjectClosure* cl): 424 _rp(rp) { 425 _saved_cl = _rp->is_alive_non_header(); 426 _rp->set_is_alive_non_header(cl); 427 } 428 429 ~ReferenceProcessorIsAliveMutator() { 430 _rp->set_is_alive_non_header(_saved_cl); 431 } 432 }; 433 434 // A utility class to temporarily change the disposition 435 // of the "discovery_is_atomic" field of the 436 // given ReferenceProcessor in the scope that contains it. 437 class ReferenceProcessorAtomicMutator: StackObj { 438 private: 439 ReferenceProcessor* _rp; 440 bool _saved_atomic_discovery; 441 442 public: 443 ReferenceProcessorAtomicMutator(ReferenceProcessor* rp, 444 bool atomic): 445 _rp(rp) { 446 _saved_atomic_discovery = _rp->discovery_is_atomic(); 447 _rp->set_atomic_discovery(atomic); 448 } 449 450 ~ReferenceProcessorAtomicMutator() { 451 _rp->set_atomic_discovery(_saved_atomic_discovery); 452 } 453 }; 454 455 456 // A utility class to temporarily change the MT processing 457 // disposition of the given ReferenceProcessor instance 458 // in the scope that contains it. 459 class ReferenceProcessorMTProcMutator: StackObj { 460 private: 461 ReferenceProcessor* _rp; 462 bool _saved_mt; 463 464 public: 465 ReferenceProcessorMTProcMutator(ReferenceProcessor* rp, 466 bool mt): 467 _rp(rp) { 468 _saved_mt = _rp->processing_is_mt(); 469 _rp->set_mt_processing(mt); 470 } 471 472 ~ReferenceProcessorMTProcMutator() { 473 _rp->set_mt_processing(_saved_mt); 474 } 475 }; 476 477 478 // This class is an interface used to implement task execution for the 479 // reference processing. 480 class AbstractRefProcTaskExecutor { 481 public: 482 483 // Abstract tasks to execute. 484 class ProcessTask; 485 class EnqueueTask; 486 487 // Executes a task using worker threads. 488 virtual void execute(ProcessTask& task) = 0; 489 virtual void execute(EnqueueTask& task) = 0; 490 491 // Switch to single threaded mode. 492 virtual void set_single_threaded_mode() { }; 493 }; 494 495 // Abstract reference processing task to execute. 496 class AbstractRefProcTaskExecutor::ProcessTask { 497 protected: 498 ProcessTask(ReferenceProcessor& ref_processor, 499 DiscoveredList refs_lists[], 500 bool marks_oops_alive) 501 : _ref_processor(ref_processor), 502 _refs_lists(refs_lists), 503 _marks_oops_alive(marks_oops_alive) 504 { } 505 506 public: 507 virtual void work(unsigned int work_id, BoolObjectClosure& is_alive, 508 OopClosure& keep_alive, 509 VoidClosure& complete_gc) = 0; 510 511 // Returns true if a task marks some oops as alive. 512 bool marks_oops_alive() const 513 { return _marks_oops_alive; } 514 515 protected: 516 ReferenceProcessor& _ref_processor; 517 DiscoveredList* _refs_lists; 518 const bool _marks_oops_alive; 519 }; 520 521 // Abstract reference processing task to execute. 522 class AbstractRefProcTaskExecutor::EnqueueTask { 523 protected: 524 EnqueueTask(ReferenceProcessor& ref_processor, 525 DiscoveredList refs_lists[], 526 HeapWord* pending_list_addr, 527 oop sentinel_ref, 528 int n_queues) 529 : _ref_processor(ref_processor), 530 _refs_lists(refs_lists), 531 _pending_list_addr(pending_list_addr), 532 _sentinel_ref(sentinel_ref), 533 _n_queues(n_queues) 534 { } 535 536 public: 537 virtual void work(unsigned int work_id) = 0; 538 539 protected: 540 ReferenceProcessor& _ref_processor; 541 DiscoveredList* _refs_lists; 542 HeapWord* _pending_list_addr; 543 oop _sentinel_ref; 544 int _n_queues; 545 }; 546 547 #endif // SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP