Mon, 02 Aug 2010 12:51:43 -0700
6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp
1 /*
2 * Copyright (c) 2001, 2009, 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 */
25 # include "incls/_precompiled.incl"
26 # include "incls/_ptrQueue.cpp.incl"
28 PtrQueue::PtrQueue(PtrQueueSet* qset_, bool perm, bool active) :
29 _qset(qset_), _buf(NULL), _index(0), _active(active),
30 _perm(perm), _lock(NULL)
31 {}
33 void PtrQueue::flush() {
34 if (!_perm && _buf != NULL) {
35 if (_index == _sz) {
36 // No work to do.
37 qset()->deallocate_buffer(_buf);
38 } else {
39 // We must NULL out the unused entries, then enqueue.
40 for (size_t i = 0; i < _index; i += oopSize) {
41 _buf[byte_index_to_index((int)i)] = NULL;
42 }
43 qset()->enqueue_complete_buffer(_buf);
44 }
45 _buf = NULL;
46 _index = 0;
47 }
48 }
51 static int byte_index_to_index(int ind) {
52 assert((ind % oopSize) == 0, "Invariant.");
53 return ind / oopSize;
54 }
56 static int index_to_byte_index(int byte_ind) {
57 return byte_ind * oopSize;
58 }
60 void PtrQueue::enqueue_known_active(void* ptr) {
61 assert(0 <= _index && _index <= _sz, "Invariant.");
62 assert(_index == 0 || _buf != NULL, "invariant");
64 while (_index == 0) {
65 handle_zero_index();
66 }
68 assert(_index > 0, "postcondition");
69 _index -= oopSize;
70 _buf[byte_index_to_index((int)_index)] = ptr;
71 assert(0 <= _index && _index <= _sz, "Invariant.");
72 }
74 void PtrQueue::locking_enqueue_completed_buffer(void** buf) {
75 assert(_lock->owned_by_self(), "Required.");
77 // We have to unlock _lock (which may be Shared_DirtyCardQ_lock) before
78 // we acquire DirtyCardQ_CBL_mon inside enqeue_complete_buffer as they
79 // have the same rank and we may get the "possible deadlock" message
80 _lock->unlock();
82 qset()->enqueue_complete_buffer(buf);
83 // We must relock only because the caller will unlock, for the normal
84 // case.
85 _lock->lock_without_safepoint_check();
86 }
89 PtrQueueSet::PtrQueueSet(bool notify_when_complete) :
90 _max_completed_queue(0),
91 _cbl_mon(NULL), _fl_lock(NULL),
92 _notify_when_complete(notify_when_complete),
93 _sz(0),
94 _completed_buffers_head(NULL),
95 _completed_buffers_tail(NULL),
96 _n_completed_buffers(0),
97 _process_completed_threshold(0), _process_completed(false),
98 _buf_free_list(NULL), _buf_free_list_sz(0)
99 {
100 _fl_owner = this;
101 }
103 void** PtrQueueSet::allocate_buffer() {
104 assert(_sz > 0, "Didn't set a buffer size.");
105 MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
106 if (_fl_owner->_buf_free_list != NULL) {
107 void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list);
108 _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next();
109 _fl_owner->_buf_free_list_sz--;
110 return res;
111 } else {
112 // Allocate space for the BufferNode in front of the buffer.
113 char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size());
114 return BufferNode::make_buffer_from_block(b);
115 }
116 }
118 void PtrQueueSet::deallocate_buffer(void** buf) {
119 assert(_sz > 0, "Didn't set a buffer size.");
120 MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
121 BufferNode *node = BufferNode::make_node_from_buffer(buf);
122 node->set_next(_fl_owner->_buf_free_list);
123 _fl_owner->_buf_free_list = node;
124 _fl_owner->_buf_free_list_sz++;
125 }
127 void PtrQueueSet::reduce_free_list() {
128 assert(_fl_owner == this, "Free list reduction is allowed only for the owner");
129 // For now we'll adopt the strategy of deleting half.
130 MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag);
131 size_t n = _buf_free_list_sz / 2;
132 while (n > 0) {
133 assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong.");
134 void* b = BufferNode::make_block_from_node(_buf_free_list);
135 _buf_free_list = _buf_free_list->next();
136 FREE_C_HEAP_ARRAY(char, b);
137 _buf_free_list_sz --;
138 n--;
139 }
140 }
142 void PtrQueue::handle_zero_index() {
143 assert(0 == _index, "Precondition.");
144 // This thread records the full buffer and allocates a new one (while
145 // holding the lock if there is one).
146 if (_buf != NULL) {
147 if (_lock) {
148 assert(_lock->owned_by_self(), "Required.");
150 // The current PtrQ may be the shared dirty card queue and
151 // may be being manipulated by more than one worker thread
152 // during a pause. Since the enqueuing of the completed
153 // buffer unlocks the Shared_DirtyCardQ_lock more than one
154 // worker thread can 'race' on reading the shared queue attributes
155 // (_buf and _index) and multiple threads can call into this
156 // routine for the same buffer. This will cause the completed
157 // buffer to be added to the CBL multiple times.
159 // We "claim" the current buffer by caching value of _buf in
160 // a local and clearing the field while holding _lock. When
161 // _lock is released (while enqueueing the completed buffer)
162 // the thread that acquires _lock will skip this code,
163 // preventing the subsequent the multiple enqueue, and
164 // install a newly allocated buffer below.
166 void** buf = _buf; // local pointer to completed buffer
167 _buf = NULL; // clear shared _buf field
169 locking_enqueue_completed_buffer(buf); // enqueue completed buffer
171 // While the current thread was enqueuing the buffer another thread
172 // may have a allocated a new buffer and inserted it into this pointer
173 // queue. If that happens then we just return so that the current
174 // thread doesn't overwrite the buffer allocated by the other thread
175 // and potentially losing some dirtied cards.
177 if (_buf != NULL) return;
178 } else {
179 if (qset()->process_or_enqueue_complete_buffer(_buf)) {
180 // Recycle the buffer. No allocation.
181 _sz = qset()->buffer_size();
182 _index = _sz;
183 return;
184 }
185 }
186 }
187 // Reallocate the buffer
188 _buf = qset()->allocate_buffer();
189 _sz = qset()->buffer_size();
190 _index = _sz;
191 assert(0 <= _index && _index <= _sz, "Invariant.");
192 }
194 bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) {
195 if (Thread::current()->is_Java_thread()) {
196 // We don't lock. It is fine to be epsilon-precise here.
197 if (_max_completed_queue == 0 || _max_completed_queue > 0 &&
198 _n_completed_buffers >= _max_completed_queue + _completed_queue_padding) {
199 bool b = mut_process_buffer(buf);
200 if (b) {
201 // True here means that the buffer hasn't been deallocated and the caller may reuse it.
202 return true;
203 }
204 }
205 }
206 // The buffer will be enqueued. The caller will have to get a new one.
207 enqueue_complete_buffer(buf);
208 return false;
209 }
211 void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) {
212 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
213 BufferNode* cbn = BufferNode::new_from_buffer(buf);
214 cbn->set_index(index);
215 if (_completed_buffers_tail == NULL) {
216 assert(_completed_buffers_head == NULL, "Well-formedness");
217 _completed_buffers_head = cbn;
218 _completed_buffers_tail = cbn;
219 } else {
220 _completed_buffers_tail->set_next(cbn);
221 _completed_buffers_tail = cbn;
222 }
223 _n_completed_buffers++;
225 if (!_process_completed && _process_completed_threshold >= 0 &&
226 _n_completed_buffers >= _process_completed_threshold) {
227 _process_completed = true;
228 if (_notify_when_complete)
229 _cbl_mon->notify();
230 }
231 debug_only(assert_completed_buffer_list_len_correct_locked());
232 }
234 int PtrQueueSet::completed_buffers_list_length() {
235 int n = 0;
236 BufferNode* cbn = _completed_buffers_head;
237 while (cbn != NULL) {
238 n++;
239 cbn = cbn->next();
240 }
241 return n;
242 }
244 void PtrQueueSet::assert_completed_buffer_list_len_correct() {
245 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
246 assert_completed_buffer_list_len_correct_locked();
247 }
249 void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() {
250 guarantee(completed_buffers_list_length() == _n_completed_buffers,
251 "Completed buffer length is wrong.");
252 }
254 void PtrQueueSet::set_buffer_size(size_t sz) {
255 assert(_sz == 0 && sz > 0, "Should be called only once.");
256 _sz = sz * oopSize;
257 }
259 // Merge lists of buffers. Notify the processing threads.
260 // The source queue is emptied as a result. The queues
261 // must share the monitor.
262 void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
263 assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
264 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
265 if (_completed_buffers_tail == NULL) {
266 assert(_completed_buffers_head == NULL, "Well-formedness");
267 _completed_buffers_head = src->_completed_buffers_head;
268 _completed_buffers_tail = src->_completed_buffers_tail;
269 } else {
270 assert(_completed_buffers_head != NULL, "Well formedness");
271 if (src->_completed_buffers_head != NULL) {
272 _completed_buffers_tail->set_next(src->_completed_buffers_head);
273 _completed_buffers_tail = src->_completed_buffers_tail;
274 }
275 }
276 _n_completed_buffers += src->_n_completed_buffers;
278 src->_n_completed_buffers = 0;
279 src->_completed_buffers_head = NULL;
280 src->_completed_buffers_tail = NULL;
282 assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
283 _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
284 "Sanity");
285 }
287 void PtrQueueSet::notify_if_necessary() {
288 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
289 if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) {
290 _process_completed = true;
291 if (_notify_when_complete)
292 _cbl_mon->notify();
293 }
294 }