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

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

author
johnc
date
Mon, 03 Aug 2009 12:59:30 -0700
changeset 1324
15c5903cf9e1
parent 1063
7bb995fbd3c0
child 1546
44f61c24ddab
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 /*
xdono@1014 2 * Copyright 2001-2009 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 // There are various techniques that require threads to be able to log
ysr@777 26 // addresses. For example, a generational write barrier might log
ysr@777 27 // the addresses of modified old-generation objects. This type supports
ysr@777 28 // this operation.
ysr@777 29
ysr@777 30 class PtrQueueSet;
ysr@777 31
apetrusenko@984 32 class PtrQueue VALUE_OBJ_CLASS_SPEC {
ysr@777 33
ysr@777 34 protected:
ysr@777 35 // The ptr queue set to which this queue belongs.
ysr@777 36 PtrQueueSet* _qset;
ysr@777 37
ysr@777 38 // Whether updates should be logged.
ysr@777 39 bool _active;
ysr@777 40
ysr@777 41 // The buffer.
ysr@777 42 void** _buf;
ysr@777 43 // The index at which an object was last enqueued. Starts at "_sz"
ysr@777 44 // (indicating an empty buffer) and goes towards zero.
ysr@777 45 size_t _index;
ysr@777 46
ysr@777 47 // The size of the buffer.
ysr@777 48 size_t _sz;
ysr@777 49
ysr@777 50 // If true, the queue is permanent, and doesn't need to deallocate
ysr@777 51 // its buffer in the destructor (since that obtains a lock which may not
ysr@777 52 // be legally locked by then.
ysr@777 53 bool _perm;
ysr@777 54
ysr@777 55 // If there is a lock associated with this buffer, this is that lock.
ysr@777 56 Mutex* _lock;
ysr@777 57
ysr@777 58 PtrQueueSet* qset() { return _qset; }
ysr@777 59
ysr@777 60 public:
ysr@777 61 // Initialize this queue to contain a null buffer, and be part of the
ysr@777 62 // given PtrQueueSet.
ysr@777 63 PtrQueue(PtrQueueSet*, bool perm = false);
ysr@777 64 // Release any contained resources.
iveresov@876 65 void flush();
iveresov@876 66 // Calls flush() when destroyed.
iveresov@876 67 ~PtrQueue() { flush(); }
ysr@777 68
ysr@777 69 // Associate a lock with a ptr queue.
ysr@777 70 void set_lock(Mutex* lock) { _lock = lock; }
ysr@777 71
ysr@777 72 void reset() { if (_buf != NULL) _index = _sz; }
ysr@777 73
ysr@777 74 // Enqueues the given "obj".
ysr@777 75 void enqueue(void* ptr) {
ysr@777 76 if (!_active) return;
ysr@777 77 else enqueue_known_active(ptr);
ysr@777 78 }
ysr@777 79
ysr@777 80 inline void handle_zero_index();
ysr@777 81 void locking_enqueue_completed_buffer(void** buf);
ysr@777 82
ysr@777 83 void enqueue_known_active(void* ptr);
ysr@777 84
ysr@777 85 size_t size() {
ysr@777 86 assert(_sz >= _index, "Invariant.");
ysr@777 87 return _buf == NULL ? 0 : _sz - _index;
ysr@777 88 }
ysr@777 89
ysr@777 90 // Set the "active" property of the queue to "b". An enqueue to an
ysr@777 91 // inactive thread is a no-op. Setting a queue to inactive resets its
ysr@777 92 // log to the empty state.
ysr@777 93 void set_active(bool b) {
ysr@777 94 _active = b;
ysr@777 95 if (!b && _buf != NULL) {
ysr@777 96 _index = _sz;
ysr@777 97 } else if (b && _buf != NULL) {
ysr@777 98 assert(_index == _sz, "invariant: queues are empty when activated.");
ysr@777 99 }
ysr@777 100 }
ysr@777 101
ysr@777 102 static int byte_index_to_index(int ind) {
ysr@777 103 assert((ind % oopSize) == 0, "Invariant.");
ysr@777 104 return ind / oopSize;
ysr@777 105 }
ysr@777 106
ysr@777 107 static int index_to_byte_index(int byte_ind) {
ysr@777 108 return byte_ind * oopSize;
ysr@777 109 }
ysr@777 110
ysr@777 111 // To support compiler.
ysr@777 112 static ByteSize byte_offset_of_index() {
ysr@777 113 return byte_offset_of(PtrQueue, _index);
ysr@777 114 }
ysr@777 115 static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); }
ysr@777 116
ysr@777 117 static ByteSize byte_offset_of_buf() {
ysr@777 118 return byte_offset_of(PtrQueue, _buf);
ysr@777 119 }
ysr@777 120 static ByteSize byte_width_of_buf() { return in_ByteSize(sizeof(void*)); }
ysr@777 121
ysr@777 122 static ByteSize byte_offset_of_active() {
ysr@777 123 return byte_offset_of(PtrQueue, _active);
ysr@777 124 }
ysr@777 125 static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); }
ysr@777 126
ysr@777 127 };
ysr@777 128
ysr@777 129 // A PtrQueueSet represents resources common to a set of pointer queues.
ysr@777 130 // In particular, the individual queues allocate buffers from this shared
ysr@777 131 // set, and return completed buffers to the set.
ysr@777 132 // All these variables are are protected by the TLOQ_CBL_mon. XXX ???
apetrusenko@984 133 class PtrQueueSet VALUE_OBJ_CLASS_SPEC {
ysr@777 134
ysr@777 135 protected:
ysr@777 136
ysr@777 137 class CompletedBufferNode: public CHeapObj {
ysr@777 138 public:
ysr@777 139 void** buf;
ysr@777 140 size_t index;
ysr@777 141 CompletedBufferNode* next;
ysr@777 142 CompletedBufferNode() : buf(NULL),
ysr@777 143 index(0), next(NULL){ }
ysr@777 144 };
ysr@777 145
ysr@777 146 Monitor* _cbl_mon; // Protects the fields below.
ysr@777 147 CompletedBufferNode* _completed_buffers_head;
ysr@777 148 CompletedBufferNode* _completed_buffers_tail;
ysr@777 149 size_t _n_completed_buffers;
ysr@777 150 size_t _process_completed_threshold;
ysr@777 151 volatile bool _process_completed;
ysr@777 152
ysr@777 153 // This (and the interpretation of the first element as a "next"
ysr@777 154 // pointer) are protected by the TLOQ_FL_lock.
ysr@777 155 Mutex* _fl_lock;
ysr@777 156 void** _buf_free_list;
ysr@777 157 size_t _buf_free_list_sz;
iveresov@1051 158 // Queue set can share a freelist. The _fl_owner variable
iveresov@1051 159 // specifies the owner. It is set to "this" by default.
iveresov@1051 160 PtrQueueSet* _fl_owner;
ysr@777 161
ysr@777 162 // The size of all buffers in the set.
ysr@777 163 size_t _sz;
ysr@777 164
ysr@777 165 bool _all_active;
ysr@777 166
ysr@777 167 // If true, notify_all on _cbl_mon when the threshold is reached.
ysr@777 168 bool _notify_when_complete;
ysr@777 169
ysr@777 170 // Maximum number of elements allowed on completed queue: after that,
ysr@777 171 // enqueuer does the work itself. Zero indicates no maximum.
ysr@777 172 int _max_completed_queue;
ysr@777 173
ysr@777 174 int completed_buffers_list_length();
ysr@777 175 void assert_completed_buffer_list_len_correct_locked();
ysr@777 176 void assert_completed_buffer_list_len_correct();
ysr@777 177
ysr@777 178 protected:
ysr@777 179 // A mutator thread does the the work of processing a buffer.
ysr@777 180 // Returns "true" iff the work is complete (and the buffer may be
ysr@777 181 // deallocated).
ysr@777 182 virtual bool mut_process_buffer(void** buf) {
ysr@777 183 ShouldNotReachHere();
ysr@777 184 return false;
ysr@777 185 }
ysr@777 186
ysr@777 187 public:
ysr@777 188 // Create an empty ptr queue set.
ysr@777 189 PtrQueueSet(bool notify_when_complete = false);
ysr@777 190
ysr@777 191 // Because of init-order concerns, we can't pass these as constructor
ysr@777 192 // arguments.
ysr@777 193 void initialize(Monitor* cbl_mon, Mutex* fl_lock,
iveresov@1051 194 int max_completed_queue = 0,
iveresov@1051 195 PtrQueueSet *fl_owner = NULL) {
ysr@777 196 _max_completed_queue = max_completed_queue;
ysr@777 197 assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
iveresov@1051 198 _cbl_mon = cbl_mon;
iveresov@1051 199 _fl_lock = fl_lock;
iveresov@1051 200 _fl_owner = (fl_owner != NULL) ? fl_owner : this;
ysr@777 201 }
ysr@777 202
ysr@777 203 // Return an empty oop array of size _sz (required to be non-zero).
ysr@777 204 void** allocate_buffer();
ysr@777 205
ysr@777 206 // Return an empty buffer to the free list. The "buf" argument is
ysr@777 207 // required to be a pointer to the head of an array of length "_sz".
ysr@777 208 void deallocate_buffer(void** buf);
ysr@777 209
ysr@777 210 // Declares that "buf" is a complete buffer.
ysr@777 211 void enqueue_complete_buffer(void** buf, size_t index = 0,
ysr@777 212 bool ignore_max_completed = false);
ysr@777 213
ysr@777 214 bool completed_buffers_exist_dirty() {
ysr@777 215 return _n_completed_buffers > 0;
ysr@777 216 }
ysr@777 217
ysr@777 218 bool process_completed_buffers() { return _process_completed; }
ysr@777 219
ysr@777 220 bool active() { return _all_active; }
ysr@777 221
ysr@777 222 // Set the buffer size. Should be called before any "enqueue" operation
ysr@777 223 // can be called. And should only be called once.
ysr@777 224 void set_buffer_size(size_t sz);
ysr@777 225
ysr@777 226 // Get the buffer size.
ysr@777 227 size_t buffer_size() { return _sz; }
ysr@777 228
ysr@777 229 // Set the number of completed buffers that triggers log processing.
ysr@777 230 void set_process_completed_threshold(size_t sz);
ysr@777 231
ysr@777 232 // Must only be called at a safe point. Indicates that the buffer free
ysr@777 233 // list size may be reduced, if that is deemed desirable.
ysr@777 234 void reduce_free_list();
ysr@777 235
ysr@777 236 size_t completed_buffers_num() { return _n_completed_buffers; }
iveresov@1051 237
iveresov@1051 238 void merge_bufferlists(PtrQueueSet* src);
iveresov@1051 239 void merge_freelists(PtrQueueSet* src);
ysr@777 240 };

mercurial