comparison src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp @ 1705:2d160770d2e5

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
author johnc
date Mon, 02 Aug 2010 12:51:43 -0700
parents c18cbe5936b8
children f95d63e2154a
comparison
equal deleted inserted replaced
1704:63f4675ac87d 1705:2d160770d2e5
1 /* 1 /*
2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
176 debug_only(assert_completed_buffer_list_len_correct_locked()); 176 debug_only(assert_completed_buffer_list_len_correct_locked());
177 return nd; 177 return nd;
178 } 178 }
179 179
180 bool DirtyCardQueueSet:: 180 bool DirtyCardQueueSet::
181 apply_closure_to_completed_buffer_helper(int worker_i, 181 apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
182 int worker_i,
182 BufferNode* nd) { 183 BufferNode* nd) {
183 if (nd != NULL) { 184 if (nd != NULL) {
184 void **buf = BufferNode::make_buffer_from_node(nd); 185 void **buf = BufferNode::make_buffer_from_node(nd);
185 size_t index = nd->index(); 186 size_t index = nd->index();
186 bool b = 187 bool b =
187 DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 188 DirtyCardQueue::apply_closure_to_buffer(cl, buf,
188 index, _sz, 189 index, _sz,
189 true, worker_i); 190 true, worker_i);
190 if (b) { 191 if (b) {
191 deallocate_buffer(buf); 192 deallocate_buffer(buf);
192 return true; // In normal case, go on to next buffer. 193 return true; // In normal case, go on to next buffer.
197 } else { 198 } else {
198 return false; 199 return false;
199 } 200 }
200 } 201 }
201 202
203 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
204 int worker_i,
205 int stop_at,
206 bool during_pause) {
207 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
208 BufferNode* nd = get_completed_buffer(stop_at);
209 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
210 if (res) Atomic::inc(&_processed_buffers_rs_thread);
211 return res;
212 }
213
202 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, 214 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i,
203 int stop_at, 215 int stop_at,
204 bool during_pause) 216 bool during_pause) {
205 { 217 return apply_closure_to_completed_buffer(_closure, worker_i,
206 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); 218 stop_at, during_pause);
207 BufferNode* nd = get_completed_buffer(stop_at);
208 bool res = apply_closure_to_completed_buffer_helper(worker_i, nd);
209 if (res) Atomic::inc(&_processed_buffers_rs_thread);
210 return res;
211 } 219 }
212 220
213 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() { 221 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() {
214 BufferNode* nd = _completed_buffers_head; 222 BufferNode* nd = _completed_buffers_head;
215 while (nd != NULL) { 223 while (nd != NULL) {
220 guarantee(b, "Should not stop early."); 228 guarantee(b, "Should not stop early.");
221 nd = nd->next(); 229 nd = nd->next();
222 } 230 }
223 } 231 }
224 232
225 void DirtyCardQueueSet::abandon_logs() { 233 // Deallocates any completed log buffers
226 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); 234 void DirtyCardQueueSet::clear() {
227 BufferNode* buffers_to_delete = NULL; 235 BufferNode* buffers_to_delete = NULL;
228 { 236 {
229 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); 237 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
230 while (_completed_buffers_head != NULL) { 238 while (_completed_buffers_head != NULL) {
231 BufferNode* nd = _completed_buffers_head; 239 BufferNode* nd = _completed_buffers_head;
240 while (buffers_to_delete != NULL) { 248 while (buffers_to_delete != NULL) {
241 BufferNode* nd = buffers_to_delete; 249 BufferNode* nd = buffers_to_delete;
242 buffers_to_delete = nd->next(); 250 buffers_to_delete = nd->next();
243 deallocate_buffer(BufferNode::make_buffer_from_node(nd)); 251 deallocate_buffer(BufferNode::make_buffer_from_node(nd));
244 } 252 }
253
254 }
255
256 void DirtyCardQueueSet::abandon_logs() {
257 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
258 clear();
245 // Since abandon is done only at safepoints, we can safely manipulate 259 // Since abandon is done only at safepoints, we can safely manipulate
246 // these queues. 260 // these queues.
247 for (JavaThread* t = Threads::first(); t; t = t->next()) { 261 for (JavaThread* t = Threads::first(); t; t = t->next()) {
248 t->dirty_card_queue().reset(); 262 t->dirty_card_queue().reset();
249 } 263 }