src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp

Mon, 03 Aug 2009 12:59:30 -0700

author
johnc
date
Mon, 03 Aug 2009 12:59:30 -0700
changeset 1324
15c5903cf9e1
parent 1051
4f360ec815ba
child 1525
fa357420e7d2
permissions
-rw-r--r--

6865703: G1: Parallelize hot card cache cleanup
Summary: Have the GC worker threads clear the hot card cache in parallel by having each worker thread claim a chunk of the card cache and process the cards in that chunk. The size of the chunks that each thread will claim is determined at VM initialization from the size of the card cache and the number of worker threads.
Reviewed-by: jmasa, tonyp

ysr@777 1 /*
ysr@777 2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
ysr@777 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
ysr@777 20 * CA 95054 USA or visit www.sun.com if you need additional information or
ysr@777 21 * have any questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 class FreeIdSet;
ysr@777 26
ysr@777 27 // A closure class for processing card table entries. Note that we don't
ysr@777 28 // require these closure objects to be stack-allocated.
ysr@777 29 class CardTableEntryClosure: public CHeapObj {
ysr@777 30 public:
ysr@777 31 // Process the card whose card table entry is "card_ptr". If returns
ysr@777 32 // "false", terminate the iteration early.
ysr@777 33 virtual bool do_card_ptr(jbyte* card_ptr, int worker_i = 0) = 0;
ysr@777 34 };
ysr@777 35
ysr@777 36 // A ptrQueue whose elements are "oops", pointers to object heads.
ysr@777 37 class DirtyCardQueue: public PtrQueue {
ysr@777 38 public:
ysr@777 39 DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) :
ysr@777 40 PtrQueue(qset_, perm)
ysr@777 41 {
ysr@777 42 // Dirty card queues are always active.
ysr@777 43 _active = true;
ysr@777 44 }
ysr@777 45 // Apply the closure to all elements, and reset the index to make the
ysr@777 46 // buffer empty. If a closure application returns "false", return
ysr@777 47 // "false" immediately, halting the iteration. If "consume" is true,
ysr@777 48 // deletes processed entries from logs.
ysr@777 49 bool apply_closure(CardTableEntryClosure* cl,
ysr@777 50 bool consume = true,
ysr@777 51 size_t worker_i = 0);
ysr@777 52
ysr@777 53 // Apply the closure to all elements of "buf", down to "index"
ysr@777 54 // (inclusive.) If returns "false", then a closure application returned
ysr@777 55 // "false", and we return immediately. If "consume" is true, entries are
ysr@777 56 // set to NULL as they are processed, so they will not be processed again
ysr@777 57 // later.
ysr@777 58 static bool apply_closure_to_buffer(CardTableEntryClosure* cl,
ysr@777 59 void** buf, size_t index, size_t sz,
ysr@777 60 bool consume = true,
ysr@777 61 int worker_i = 0);
ysr@777 62 void **get_buf() { return _buf;}
ysr@777 63 void set_buf(void **buf) {_buf = buf;}
ysr@777 64 size_t get_index() { return _index;}
ysr@777 65 void reinitialize() { _buf = 0; _sz = 0; _index = 0;}
ysr@777 66 };
ysr@777 67
ysr@777 68
ysr@777 69
ysr@777 70 class DirtyCardQueueSet: public PtrQueueSet {
ysr@777 71 CardTableEntryClosure* _closure;
ysr@777 72
ysr@777 73 DirtyCardQueue _shared_dirty_card_queue;
ysr@777 74
ysr@777 75 // Override.
ysr@777 76 bool mut_process_buffer(void** buf);
ysr@777 77
ysr@777 78 // Protected by the _cbl_mon.
ysr@777 79 FreeIdSet* _free_ids;
ysr@777 80
ysr@777 81 // The number of completed buffers processed by mutator and rs thread,
ysr@777 82 // respectively.
ysr@777 83 jint _processed_buffers_mut;
ysr@777 84 jint _processed_buffers_rs_thread;
ysr@777 85
ysr@777 86 public:
ysr@777 87 DirtyCardQueueSet();
ysr@777 88
ysr@777 89 void initialize(Monitor* cbl_mon, Mutex* fl_lock,
ysr@777 90 int max_completed_queue = 0,
iveresov@1051 91 Mutex* lock = NULL, PtrQueueSet* fl_owner = NULL);
ysr@777 92
ysr@777 93 // The number of parallel ids that can be claimed to allow collector or
ysr@777 94 // mutator threads to do card-processing work.
ysr@777 95 static size_t num_par_ids();
ysr@777 96
ysr@777 97 static void handle_zero_index_for_thread(JavaThread* t);
ysr@777 98
ysr@777 99 // Register "blk" as "the closure" for all queues. Only one such closure
ysr@777 100 // is allowed. The "apply_closure_to_completed_buffer" method will apply
ysr@777 101 // this closure to a completed buffer, and "iterate_closure_all_threads"
ysr@777 102 // applies it to partially-filled buffers (the latter should only be done
ysr@777 103 // with the world stopped).
ysr@777 104 void set_closure(CardTableEntryClosure* closure);
ysr@777 105
ysr@777 106 // If there is a registered closure for buffers, apply it to all entries
ysr@777 107 // in all currently-active buffers. This should only be applied at a
ysr@777 108 // safepoint. (Currently must not be called in parallel; this should
ysr@777 109 // change in the future.) If "consume" is true, processed entries are
ysr@777 110 // discarded.
ysr@777 111 void iterate_closure_all_threads(bool consume = true,
ysr@777 112 size_t worker_i = 0);
ysr@777 113
ysr@777 114 // If there exists some completed buffer, pop it, then apply the
ysr@777 115 // registered closure to all its elements, nulling out those elements
ysr@777 116 // processed. If all elements are processed, returns "true". If no
ysr@777 117 // completed buffers exist, returns false. If a completed buffer exists,
ysr@777 118 // but is only partially completed before a "yield" happens, the
ysr@777 119 // partially completed buffer (with its processed elements set to NULL)
ysr@777 120 // is returned to the completed buffer set, and this call returns false.
ysr@777 121 bool apply_closure_to_completed_buffer(int worker_i = 0,
ysr@777 122 int stop_at = 0,
ysr@777 123 bool with_CAS = false);
ysr@777 124 bool apply_closure_to_completed_buffer_helper(int worker_i,
ysr@777 125 CompletedBufferNode* nd);
ysr@777 126
ysr@777 127 CompletedBufferNode* get_completed_buffer_CAS();
ysr@777 128 CompletedBufferNode* get_completed_buffer_lock(int stop_at);
ysr@777 129 // Applies the current closure to all completed buffers,
ysr@777 130 // non-consumptively.
ysr@777 131 void apply_closure_to_all_completed_buffers();
ysr@777 132
ysr@777 133 DirtyCardQueue* shared_dirty_card_queue() {
ysr@777 134 return &_shared_dirty_card_queue;
ysr@777 135 }
ysr@777 136
ysr@777 137 // If a full collection is happening, reset partial logs, and ignore
ysr@777 138 // completed ones: the full collection will make them all irrelevant.
ysr@777 139 void abandon_logs();
ysr@777 140
ysr@777 141 // If any threads have partial logs, add them to the global list of logs.
ysr@777 142 void concatenate_logs();
ysr@777 143 void clear_n_completed_buffers() { _n_completed_buffers = 0;}
ysr@777 144
ysr@777 145 jint processed_buffers_mut() {
ysr@777 146 return _processed_buffers_mut;
ysr@777 147 }
ysr@777 148 jint processed_buffers_rs_thread() {
ysr@777 149 return _processed_buffers_rs_thread;
ysr@777 150 }
ysr@777 151
ysr@777 152 };

mercurial