Skip to content

Commit b256989

Browse files
author
Kim Barrett
committed
6899049: G1: Clean up code in ptrQueue.[ch]pp and ptrQueue.inline.hpp
Simplify indexing, address obsolete code, improve access/type checking. Reviewed-by: tschatzl, pliden
1 parent f25b785 commit b256989

File tree

6 files changed

+145
-112
lines changed

6 files changed

+145
-112
lines changed

hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@
3232
#include "runtime/safepoint.hpp"
3333
#include "runtime/thread.inline.hpp"
3434

35+
DirtyCardQueue::DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent) :
36+
// Dirty card queues are always active, so we create them with their
37+
// active field set to true.
38+
PtrQueue(qset, permanent, true /* active */)
39+
{ }
40+
41+
DirtyCardQueue::~DirtyCardQueue() {
42+
if (!is_permanent()) {
43+
flush();
44+
}
45+
}
46+
3547
bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
3648
bool consume,
3749
uint worker_i) {
@@ -40,7 +52,9 @@ bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
4052
res = apply_closure_to_buffer(cl, _buf, _index, _sz,
4153
consume,
4254
worker_i);
43-
if (res && consume) _index = _sz;
55+
if (res && consume) {
56+
_index = _sz;
57+
}
4458
}
4559
return res;
4660
}
@@ -51,14 +65,18 @@ bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl,
5165
bool consume,
5266
uint worker_i) {
5367
if (cl == NULL) return true;
54-
for (size_t i = index; i < sz; i += oopSize) {
55-
int ind = byte_index_to_index((int)i);
56-
jbyte* card_ptr = (jbyte*)buf[ind];
68+
size_t limit = byte_index_to_index(sz);
69+
for (size_t i = byte_index_to_index(index); i < limit; ++i) {
70+
jbyte* card_ptr = static_cast<jbyte*>(buf[i]);
5771
if (card_ptr != NULL) {
5872
// Set the entry to null, so we don't do it again (via the test
5973
// above) if we reconsider this buffer.
60-
if (consume) buf[ind] = NULL;
61-
if (!cl->do_card_ptr(card_ptr, worker_i)) return false;
74+
if (consume) {
75+
buf[i] = NULL;
76+
}
77+
if (!cl->do_card_ptr(card_ptr, worker_i)) {
78+
return false;
79+
}
6280
}
6381
}
6482
return true;
@@ -71,7 +89,7 @@ bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl,
7189
DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
7290
PtrQueueSet(notify_when_complete),
7391
_mut_process_closure(NULL),
74-
_shared_dirty_card_queue(this, true /*perm*/),
92+
_shared_dirty_card_queue(this, true /* permanent */),
7593
_free_ids(NULL),
7694
_processed_buffers_mut(0), _processed_buffers_rs_thread(0)
7795
{
@@ -83,13 +101,19 @@ uint DirtyCardQueueSet::num_par_ids() {
83101
return (uint)os::processor_count();
84102
}
85103

86-
void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
104+
void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl,
105+
Monitor* cbl_mon,
106+
Mutex* fl_lock,
87107
int process_completed_threshold,
88108
int max_completed_queue,
89-
Mutex* lock, PtrQueueSet* fl_owner) {
109+
Mutex* lock,
110+
DirtyCardQueueSet* fl_owner) {
90111
_mut_process_closure = cl;
91-
PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold,
92-
max_completed_queue, fl_owner);
112+
PtrQueueSet::initialize(cbl_mon,
113+
fl_lock,
114+
process_completed_threshold,
115+
max_completed_queue,
116+
fl_owner);
93117
set_buffer_size(G1UpdateBufferSize);
94118
_shared_dirty_card_queue.set_lock(lock);
95119
_free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
@@ -103,7 +127,7 @@ void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl,
103127
bool consume,
104128
uint worker_i) {
105129
assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
106-
for(JavaThread* t = Threads::first(); t; t = t->next()) {
130+
for (JavaThread* t = Threads::first(); t; t = t->next()) {
107131
bool b = t->dirty_card_queue().apply_closure(cl, consume);
108132
guarantee(b, "Should not be interrupted.");
109133
}
@@ -160,8 +184,7 @@ bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
160184
}
161185

162186

163-
BufferNode*
164-
DirtyCardQueueSet::get_completed_buffer(int stop_at) {
187+
BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) {
165188
BufferNode* nd = NULL;
166189
MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
167190

@@ -178,14 +201,13 @@ DirtyCardQueueSet::get_completed_buffer(int stop_at) {
178201
_n_completed_buffers--;
179202
assert(_n_completed_buffers >= 0, "Invariant");
180203
}
181-
debug_only(assert_completed_buffer_list_len_correct_locked());
204+
DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
182205
return nd;
183206
}
184207

185-
bool DirtyCardQueueSet::
186-
apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
187-
uint worker_i,
188-
BufferNode* nd) {
208+
bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
209+
uint worker_i,
210+
BufferNode* nd) {
189211
if (nd != NULL) {
190212
void **buf = BufferNode::make_buffer_from_node(nd);
191213
size_t index = nd->index();
@@ -259,7 +281,7 @@ void DirtyCardQueueSet::clear() {
259281
}
260282
_n_completed_buffers = 0;
261283
_completed_buffers_tail = NULL;
262-
debug_only(assert_completed_buffer_list_len_correct_locked());
284+
DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
263285
}
264286
while (buffers_to_delete != NULL) {
265287
BufferNode* nd = buffers_to_delete;
@@ -291,10 +313,11 @@ void DirtyCardQueueSet::concatenate_logs() {
291313
for (JavaThread* t = Threads::first(); t; t = t->next()) {
292314
DirtyCardQueue& dcq = t->dirty_card_queue();
293315
if (dcq.size() != 0) {
294-
void **buf = t->dirty_card_queue().get_buf();
316+
void** buf = dcq.get_buf();
295317
// We must NULL out the unused entries, then enqueue.
296-
for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) {
297-
buf[PtrQueue::byte_index_to_index((int)i)] = NULL;
318+
size_t limit = dcq.byte_index_to_index(dcq.get_index());
319+
for (size_t i = 0; i < limit; ++i) {
320+
buf[i] = NULL;
298321
}
299322
enqueue_complete_buffer(dcq.get_buf(), dcq.get_index());
300323
dcq.reinitialize();

hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "memory/allocation.hpp"
3030

3131
class FreeIdSet;
32+
class DirtyCardQueueSet;
3233

3334
// A closure class for processing card table entries. Note that we don't
3435
// require these closure objects to be stack-allocated.
@@ -42,14 +43,11 @@ class CardTableEntryClosure: public CHeapObj<mtGC> {
4243
// A ptrQueue whose elements are "oops", pointers to object heads.
4344
class DirtyCardQueue: public PtrQueue {
4445
public:
45-
DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) :
46-
// Dirty card queues are always active, so we create them with their
47-
// active field set to true.
48-
PtrQueue(qset_, perm, true /* active */) { }
46+
DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent = false);
4947

5048
// Flush before destroying; queue may be used to capture pending work while
5149
// doing something else, with auto-flush on completion.
52-
~DirtyCardQueue() { if (!is_permanent()) flush(); }
50+
~DirtyCardQueue();
5351

5452
// Process queue entries and release resources.
5553
void flush() { flush_impl(); }
@@ -72,7 +70,6 @@ class DirtyCardQueue: public PtrQueue {
7270
bool consume = true,
7371
uint worker_i = 0);
7472
void **get_buf() { return _buf;}
75-
void set_buf(void **buf) {_buf = buf;}
7673
size_t get_index() { return _index;}
7774
void reinitialize() { _buf = 0; _sz = 0; _index = 0;}
7875
};
@@ -101,10 +98,13 @@ class DirtyCardQueueSet: public PtrQueueSet {
10198
public:
10299
DirtyCardQueueSet(bool notify_when_complete = true);
103100

104-
void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
101+
void initialize(CardTableEntryClosure* cl,
102+
Monitor* cbl_mon,
103+
Mutex* fl_lock,
105104
int process_completed_threshold,
106105
int max_completed_queue,
107-
Mutex* lock, PtrQueueSet* fl_owner = NULL);
106+
Mutex* lock,
107+
DirtyCardQueueSet* fl_owner = NULL);
108108

109109
// The number of parallel ids that can be claimed to allow collector or
110110
// mutator threads to do card-processing work.

hotspot/src/share/vm/gc/g1/ptrQueue.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,25 @@
3030
#include "runtime/mutexLocker.hpp"
3131
#include "runtime/thread.inline.hpp"
3232

33-
PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
33+
PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) :
3434
_qset(qset), _buf(NULL), _index(0), _sz(0), _active(active),
35-
_perm(perm), _lock(NULL)
35+
_permanent(permanent), _lock(NULL)
3636
{}
3737

3838
PtrQueue::~PtrQueue() {
39-
assert(_perm || (_buf == NULL), "queue must be flushed before delete");
39+
assert(_permanent || (_buf == NULL), "queue must be flushed before delete");
4040
}
4141

4242
void PtrQueue::flush_impl() {
43-
if (!_perm && _buf != NULL) {
43+
if (!_permanent && _buf != NULL) {
4444
if (_index == _sz) {
4545
// No work to do.
4646
qset()->deallocate_buffer(_buf);
4747
} else {
4848
// We must NULL out the unused entries, then enqueue.
49-
for (size_t i = 0; i < _index; i += oopSize) {
50-
_buf[byte_index_to_index((int)i)] = NULL;
49+
size_t limit = byte_index_to_index(_index);
50+
for (size_t i = 0; i < limit; ++i) {
51+
_buf[i] = NULL;
5152
}
5253
qset()->enqueue_complete_buffer(_buf);
5354
}
@@ -66,8 +67,8 @@ void PtrQueue::enqueue_known_active(void* ptr) {
6667
}
6768

6869
assert(_index > 0, "postcondition");
69-
_index -= oopSize;
70-
_buf[byte_index_to_index((int)_index)] = ptr;
70+
_index -= sizeof(void*);
71+
_buf[byte_index_to_index(_index)] = ptr;
7172
assert(_index <= _sz, "Invariant.");
7273
}
7374

@@ -100,6 +101,26 @@ PtrQueueSet::PtrQueueSet(bool notify_when_complete) :
100101
_fl_owner = this;
101102
}
102103

104+
PtrQueueSet::~PtrQueueSet() {
105+
// There are presently only a couple (derived) instances ever
106+
// created, and they are permanent, so no harm currently done by
107+
// doing nothing here.
108+
}
109+
110+
void PtrQueueSet::initialize(Monitor* cbl_mon,
111+
Mutex* fl_lock,
112+
int process_completed_threshold,
113+
int max_completed_queue,
114+
PtrQueueSet *fl_owner) {
115+
_max_completed_queue = max_completed_queue;
116+
_process_completed_threshold = process_completed_threshold;
117+
_completed_queue_padding = 0;
118+
assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
119+
_cbl_mon = cbl_mon;
120+
_fl_lock = fl_lock;
121+
_fl_owner = (fl_owner != NULL) ? fl_owner : this;
122+
}
123+
103124
void** PtrQueueSet::allocate_buffer() {
104125
assert(_sz > 0, "Didn't set a buffer size.");
105126
MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag);
@@ -233,7 +254,7 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) {
233254
if (_notify_when_complete)
234255
_cbl_mon->notify();
235256
}
236-
debug_only(assert_completed_buffer_list_len_correct_locked());
257+
DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
237258
}
238259

239260
int PtrQueueSet::completed_buffers_list_length() {
@@ -258,7 +279,7 @@ void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() {
258279

259280
void PtrQueueSet::set_buffer_size(size_t sz) {
260281
assert(_sz == 0 && sz > 0, "Should be called only once.");
261-
_sz = sz * oopSize;
282+
_sz = sz * sizeof(void*);
262283
}
263284

264285
// Merge lists of buffers. Notify the processing threads.

hotspot/src/share/vm/gc/g1/ptrQueue.hpp

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,44 +40,49 @@ class PtrQueueSet;
4040
class PtrQueue VALUE_OBJ_CLASS_SPEC {
4141
friend class VMStructs;
4242

43-
protected:
43+
// Noncopyable - not defined.
44+
PtrQueue(const PtrQueue&);
45+
PtrQueue& operator=(const PtrQueue&);
46+
4447
// The ptr queue set to which this queue belongs.
45-
PtrQueueSet* _qset;
48+
PtrQueueSet* const _qset;
4649

4750
// Whether updates should be logged.
4851
bool _active;
4952

53+
// If true, the queue is permanent, and doesn't need to deallocate
54+
// its buffer in the destructor (since that obtains a lock which may not
55+
// be legally locked by then.
56+
const bool _permanent;
57+
58+
protected:
5059
// The buffer.
5160
void** _buf;
52-
// The index at which an object was last enqueued. Starts at "_sz"
61+
// The (byte) index at which an object was last enqueued. Starts at "_sz"
5362
// (indicating an empty buffer) and goes towards zero.
5463
size_t _index;
5564

56-
// The size of the buffer.
65+
// The (byte) size of the buffer.
5766
size_t _sz;
5867

59-
// If true, the queue is permanent, and doesn't need to deallocate
60-
// its buffer in the destructor (since that obtains a lock which may not
61-
// be legally locked by then.
62-
bool _perm;
63-
6468
// If there is a lock associated with this buffer, this is that lock.
6569
Mutex* _lock;
6670

6771
PtrQueueSet* qset() { return _qset; }
68-
bool is_permanent() const { return _perm; }
72+
bool is_permanent() const { return _permanent; }
6973

7074
// Process queue entries and release resources, if not permanent.
7175
void flush_impl();
7276

73-
public:
7477
// Initialize this queue to contain a null buffer, and be part of the
7578
// given PtrQueueSet.
76-
PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
79+
PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false);
7780

7881
// Requires queue flushed or permanent.
7982
~PtrQueue();
8083

84+
public:
85+
8186
// Associate a lock with a ptr queue.
8287
void set_lock(Mutex* lock) { _lock = lock; }
8388

@@ -129,13 +134,9 @@ class PtrQueue VALUE_OBJ_CLASS_SPEC {
129134

130135
bool is_active() { return _active; }
131136

132-
static int byte_index_to_index(int ind) {
133-
assert((ind % oopSize) == 0, "Invariant.");
134-
return ind / oopSize;
135-
}
136-
137-
static int index_to_byte_index(int byte_ind) {
138-
return byte_ind * oopSize;
137+
static size_t byte_index_to_index(size_t ind) {
138+
assert((ind % sizeof(void*)) == 0, "Invariant.");
139+
return ind / sizeof(void*);
139140
}
140141

141142
// To support compiler.
@@ -246,26 +247,21 @@ class PtrQueueSet VALUE_OBJ_CLASS_SPEC {
246247
return false;
247248
}
248249

249-
public:
250250
// Create an empty ptr queue set.
251251
PtrQueueSet(bool notify_when_complete = false);
252+
~PtrQueueSet();
252253

253254
// Because of init-order concerns, we can't pass these as constructor
254255
// arguments.
255-
void initialize(Monitor* cbl_mon, Mutex* fl_lock,
256+
void initialize(Monitor* cbl_mon,
257+
Mutex* fl_lock,
256258
int process_completed_threshold,
257259
int max_completed_queue,
258-
PtrQueueSet *fl_owner = NULL) {
259-
_max_completed_queue = max_completed_queue;
260-
_process_completed_threshold = process_completed_threshold;
261-
_completed_queue_padding = 0;
262-
assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
263-
_cbl_mon = cbl_mon;
264-
_fl_lock = fl_lock;
265-
_fl_owner = (fl_owner != NULL) ? fl_owner : this;
266-
}
260+
PtrQueueSet *fl_owner = NULL);
261+
262+
public:
267263

268-
// Return an empty oop array of size _sz (required to be non-zero).
264+
// Return an empty array of size _sz (required to be non-zero).
269265
void** allocate_buffer();
270266

271267
// Return an empty buffer to the free list. The "buf" argument is

0 commit comments

Comments
 (0)