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 */
24
25 #include "precompiled.hpp"
26 #include "gc/g1/g1RedirtyCardsQueue.hpp"
27 #include "runtime/atomic.hpp"
28 #include "utilities/debug.hpp"
29 #include "utilities/macros.hpp"
30
31 // G1RedirtyCardsBufferList
32
33 G1RedirtyCardsBufferList::G1RedirtyCardsBufferList() :
34 _head(NULL), _tail(NULL), _entry_count(0) {}
35
36 G1RedirtyCardsBufferList::G1RedirtyCardsBufferList(BufferNode* head,
37 BufferNode* tail,
38 size_t entry_count) :
39 _head(head), _tail(tail), _entry_count(entry_count)
40 {
41 assert((_head == NULL) == (_tail == NULL), "invariant");
42 assert((_head == NULL) == (_entry_count == 0), "invariant");
43 }
44
45 // G1RedirtyCardsQueueBase::LocalQSet
46
47 G1RedirtyCardsQueueBase::LocalQSet::LocalQSet(G1RedirtyCardsQueueSet* shared_qset) :
48 PtrQueueSet(),
49 _shared_qset(shared_qset),
50 _buffers()
51 {
52 PtrQueueSet::initialize(_shared_qset->allocator());
53 }
54
55 G1RedirtyCardsQueueBase::LocalQSet::~LocalQSet() {
56 assert(_buffers._head == NULL, "unflushed qset");
57 assert(_buffers._tail == NULL, "invariant");
58 assert(_buffers._entry_count == 0, "invariant");
59 }
60
61 void G1RedirtyCardsQueueBase::LocalQSet::enqueue_completed_buffer(BufferNode* node) {
62 _buffers._entry_count += buffer_size() - node->index();
63 node->set_next(_buffers._head);
64 _buffers._head = node;
65 if (_buffers._tail == NULL) {
66 _buffers._tail = node;
67 }
68 }
69
70 G1RedirtyCardsBufferList G1RedirtyCardsQueueBase::LocalQSet::take_all_completed_buffers() {
71 G1RedirtyCardsBufferList result = _buffers;
72 _buffers = G1RedirtyCardsBufferList();
73 return result;
74 }
75
76 void G1RedirtyCardsQueueBase::LocalQSet::flush() {
77 _shared_qset->merge_bufferlist(this);
78 }
79
80 // G1RedirtyCardsQueue
81
82 G1RedirtyCardsQueue::G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset) :
83 G1RedirtyCardsQueueBase(qset), // Init _local_qset before passing to PtrQueue.
84 PtrQueue(&_local_qset, true /* active (always) */)
85 {}
86
87 G1RedirtyCardsQueue::~G1RedirtyCardsQueue() {
88 flush();
89 }
90
91 void G1RedirtyCardsQueue::handle_completed_buffer() {
92 enqueue_completed_buffer();
109 initialize(allocator);
110 }
111
112 G1RedirtyCardsQueueSet::~G1RedirtyCardsQueueSet() {
113 verify_empty();
114 }
115
116 #ifdef ASSERT
117 void G1RedirtyCardsQueueSet::verify_empty() const {
118 assert(_list.empty(), "precondition");
119 assert(_tail == NULL, "invariant");
120 assert(_entry_count == 0, "invariant");
121 }
122 #endif // ASSERT
123
124 BufferNode* G1RedirtyCardsQueueSet::all_completed_buffers() const {
125 DEBUG_ONLY(_collecting = false;)
126 return _list.top();
127 }
128
129 G1RedirtyCardsBufferList G1RedirtyCardsQueueSet::take_all_completed_buffers() {
130 DEBUG_ONLY(_collecting = false;)
131 G1RedirtyCardsBufferList result(_list.pop_all(), _tail, _entry_count);
132 _tail = NULL;
133 _entry_count = 0;
134 DEBUG_ONLY(_collecting = true;)
135 return result;
136 }
137
138 void G1RedirtyCardsQueueSet::update_tail(BufferNode* node) {
139 // Node is the tail of a (possibly single element) list just prepended to
140 // _list. If, after that prepend, node's follower is NULL, then node is
141 // also the tail of _list, so record it as such.
142 if (node->next() == NULL) {
143 assert(_tail == NULL, "invariant");
144 _tail = node;
145 }
146 }
147
148 void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) {
149 assert(_collecting, "precondition");
150 Atomic::add(buffer_size() - node->index(), &_entry_count);
151 _list.push(*node);
152 update_tail(node);
153 }
154
155 void G1RedirtyCardsQueueSet::merge_bufferlist(LocalQSet* src) {
156 assert(_collecting, "precondition");
157 const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
158 if (from._head != NULL) {
159 assert(from._tail != NULL, "invariant");
160 Atomic::add(from._entry_count, &_entry_count);
161 _list.prepend(*from._head, *from._tail);
162 update_tail(from._tail);
163 }
164 }
|
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 */
24
25 #include "precompiled.hpp"
26 #include "gc/g1/g1RedirtyCardsQueue.hpp"
27 #include "runtime/atomic.hpp"
28 #include "utilities/debug.hpp"
29 #include "utilities/macros.hpp"
30
31 // G1RedirtyCardsQueueBase::LocalQSet
32
33 G1RedirtyCardsQueueBase::LocalQSet::LocalQSet(G1RedirtyCardsQueueSet* shared_qset) :
34 PtrQueueSet(),
35 _shared_qset(shared_qset),
36 _buffers()
37 {
38 PtrQueueSet::initialize(_shared_qset->allocator());
39 }
40
41 G1RedirtyCardsQueueBase::LocalQSet::~LocalQSet() {
42 assert(_buffers._head == NULL, "unflushed qset");
43 assert(_buffers._tail == NULL, "invariant");
44 assert(_buffers._entry_count == 0, "invariant");
45 }
46
47 void G1RedirtyCardsQueueBase::LocalQSet::enqueue_completed_buffer(BufferNode* node) {
48 _buffers._entry_count += buffer_size() - node->index();
49 node->set_next(_buffers._head);
50 _buffers._head = node;
51 if (_buffers._tail == NULL) {
52 _buffers._tail = node;
53 }
54 }
55
56 G1BufferNodeList G1RedirtyCardsQueueBase::LocalQSet::take_all_completed_buffers() {
57 G1BufferNodeList result = _buffers;
58 _buffers = G1BufferNodeList();
59 return result;
60 }
61
62 void G1RedirtyCardsQueueBase::LocalQSet::flush() {
63 _shared_qset->merge_bufferlist(this);
64 }
65
66 // G1RedirtyCardsQueue
67
68 G1RedirtyCardsQueue::G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset) :
69 G1RedirtyCardsQueueBase(qset), // Init _local_qset before passing to PtrQueue.
70 PtrQueue(&_local_qset, true /* active (always) */)
71 {}
72
73 G1RedirtyCardsQueue::~G1RedirtyCardsQueue() {
74 flush();
75 }
76
77 void G1RedirtyCardsQueue::handle_completed_buffer() {
78 enqueue_completed_buffer();
95 initialize(allocator);
96 }
97
98 G1RedirtyCardsQueueSet::~G1RedirtyCardsQueueSet() {
99 verify_empty();
100 }
101
102 #ifdef ASSERT
103 void G1RedirtyCardsQueueSet::verify_empty() const {
104 assert(_list.empty(), "precondition");
105 assert(_tail == NULL, "invariant");
106 assert(_entry_count == 0, "invariant");
107 }
108 #endif // ASSERT
109
110 BufferNode* G1RedirtyCardsQueueSet::all_completed_buffers() const {
111 DEBUG_ONLY(_collecting = false;)
112 return _list.top();
113 }
114
115 G1BufferNodeList G1RedirtyCardsQueueSet::take_all_completed_buffers() {
116 DEBUG_ONLY(_collecting = false;)
117 G1BufferNodeList result(_list.pop_all(), _tail, _entry_count);
118 _tail = NULL;
119 _entry_count = 0;
120 DEBUG_ONLY(_collecting = true;)
121 return result;
122 }
123
124 void G1RedirtyCardsQueueSet::update_tail(BufferNode* node) {
125 // Node is the tail of a (possibly single element) list just prepended to
126 // _list. If, after that prepend, node's follower is NULL, then node is
127 // also the tail of _list, so record it as such.
128 if (node->next() == NULL) {
129 assert(_tail == NULL, "invariant");
130 _tail = node;
131 }
132 }
133
134 void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) {
135 assert(_collecting, "precondition");
136 Atomic::add(buffer_size() - node->index(), &_entry_count);
137 _list.push(*node);
138 update_tail(node);
139 }
140
141 void G1RedirtyCardsQueueSet::merge_bufferlist(LocalQSet* src) {
142 assert(_collecting, "precondition");
143 const G1BufferNodeList from = src->take_all_completed_buffers();
144 if (from._head != NULL) {
145 assert(from._tail != NULL, "invariant");
146 Atomic::add(from._entry_count, &_entry_count);
147 _list.prepend(*from._head, *from._tail);
148 update_tail(from._tail);
149 }
150 }
|