Thu, 06 Jan 2011 23:50:02 -0800
7008136: CMS: assert((HeapWord*)nextChunk <= _limit) failed: sweep invariant
Summary: The recorded _sweep_limit may not necessarily remain a block boundary as the old generation expands during a concurrent cycle. Terminal actions inside the sweep closure need to be aware of this as they cross over the limit.
Reviewed-by: johnc, minqi
1 /*
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.
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 #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
26 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
28 #include "gc_implementation/shared/allocationStats.hpp"
30 class CompactibleFreeListSpace;
32 // A class for maintaining a free list of FreeChunk's. The FreeList
33 // maintains a the structure of the list (head, tail, etc.) plus
34 // statistics for allocations from the list. The links between items
35 // are not part of FreeList. The statistics are
36 // used to make decisions about coalescing FreeChunk's when they
37 // are swept during collection.
38 //
39 // See the corresponding .cpp file for a description of the specifics
40 // for that implementation.
42 class Mutex;
43 class TreeList;
45 class FreeList VALUE_OBJ_CLASS_SPEC {
46 friend class CompactibleFreeListSpace;
47 friend class VMStructs;
48 friend class PrintTreeCensusClosure;
50 protected:
51 TreeList* _parent;
52 TreeList* _left;
53 TreeList* _right;
55 private:
56 FreeChunk* _head; // Head of list of free chunks
57 FreeChunk* _tail; // Tail of list of free chunks
58 size_t _size; // Size in Heap words of each chunk
59 ssize_t _count; // Number of entries in list
60 size_t _hint; // next larger size list with a positive surplus
62 AllocationStats _allocation_stats; // allocation-related statistics
64 #ifdef ASSERT
65 Mutex* _protecting_lock;
66 #endif
68 // Asserts false if the protecting lock (if any) is not held.
69 void assert_proper_lock_protection_work() const PRODUCT_RETURN;
70 void assert_proper_lock_protection() const {
71 #ifdef ASSERT
72 if (_protecting_lock != NULL)
73 assert_proper_lock_protection_work();
74 #endif
75 }
77 // Initialize the allocation statistics.
78 protected:
79 void init_statistics(bool split_birth = false);
80 void set_count(ssize_t v) { _count = v;}
81 void increment_count() {
82 _count++;
83 }
85 void decrement_count() {
86 _count--;
87 assert(_count >= 0, "Count should not be negative");
88 }
90 public:
91 // Constructor
92 // Construct a list without any entries.
93 FreeList();
94 // Construct a list with "fc" as the first (and lone) entry in the list.
95 FreeList(FreeChunk* fc);
96 // Construct a list which will have a FreeChunk at address "addr" and
97 // of size "size" as the first (and lone) entry in the list.
98 FreeList(HeapWord* addr, size_t size);
100 // Reset the head, tail, hint, and count of a free list.
101 void reset(size_t hint);
103 // Declare the current free list to be protected by the given lock.
104 #ifdef ASSERT
105 void set_protecting_lock(Mutex* protecting_lock) {
106 _protecting_lock = protecting_lock;
107 }
108 #endif
110 // Accessors.
111 FreeChunk* head() const {
112 assert_proper_lock_protection();
113 return _head;
114 }
115 void set_head(FreeChunk* v) {
116 assert_proper_lock_protection();
117 _head = v;
118 assert(!_head || _head->size() == _size, "bad chunk size");
119 }
120 // Set the head of the list and set the prev field of non-null
121 // values to NULL.
122 void link_head(FreeChunk* v) {
123 assert_proper_lock_protection();
124 set_head(v);
125 // If this method is not used (just set the head instead),
126 // this check can be avoided.
127 if (v != NULL) {
128 v->linkPrev(NULL);
129 }
130 }
132 FreeChunk* tail() const {
133 assert_proper_lock_protection();
134 return _tail;
135 }
136 void set_tail(FreeChunk* v) {
137 assert_proper_lock_protection();
138 _tail = v;
139 assert(!_tail || _tail->size() == _size, "bad chunk size");
140 }
141 // Set the tail of the list and set the next field of non-null
142 // values to NULL.
143 void link_tail(FreeChunk* v) {
144 assert_proper_lock_protection();
145 set_tail(v);
146 if (v != NULL) {
147 v->clearNext();
148 }
149 }
151 // No locking checks in read-accessors: lock-free reads (only) are benign.
152 // Readers are expected to have the lock if they are doing work that
153 // requires atomicity guarantees in sections of code.
154 size_t size() const {
155 return _size;
156 }
157 void set_size(size_t v) {
158 assert_proper_lock_protection();
159 _size = v;
160 }
161 ssize_t count() const {
162 return _count;
163 }
164 size_t hint() const {
165 return _hint;
166 }
167 void set_hint(size_t v) {
168 assert_proper_lock_protection();
169 assert(v == 0 || _size < v, "Bad hint"); _hint = v;
170 }
172 // Accessors for statistics
173 AllocationStats* allocation_stats() {
174 assert_proper_lock_protection();
175 return &_allocation_stats;
176 }
178 ssize_t desired() const {
179 return _allocation_stats.desired();
180 }
181 void set_desired(ssize_t v) {
182 assert_proper_lock_protection();
183 _allocation_stats.set_desired(v);
184 }
185 void compute_desired(float inter_sweep_current,
186 float inter_sweep_estimate,
187 float intra_sweep_estimate) {
188 assert_proper_lock_protection();
189 _allocation_stats.compute_desired(_count,
190 inter_sweep_current,
191 inter_sweep_estimate,
192 intra_sweep_estimate);
193 }
194 ssize_t coalDesired() const {
195 return _allocation_stats.coalDesired();
196 }
197 void set_coalDesired(ssize_t v) {
198 assert_proper_lock_protection();
199 _allocation_stats.set_coalDesired(v);
200 }
202 ssize_t surplus() const {
203 return _allocation_stats.surplus();
204 }
205 void set_surplus(ssize_t v) {
206 assert_proper_lock_protection();
207 _allocation_stats.set_surplus(v);
208 }
209 void increment_surplus() {
210 assert_proper_lock_protection();
211 _allocation_stats.increment_surplus();
212 }
213 void decrement_surplus() {
214 assert_proper_lock_protection();
215 _allocation_stats.decrement_surplus();
216 }
218 ssize_t bfrSurp() const {
219 return _allocation_stats.bfrSurp();
220 }
221 void set_bfrSurp(ssize_t v) {
222 assert_proper_lock_protection();
223 _allocation_stats.set_bfrSurp(v);
224 }
225 ssize_t prevSweep() const {
226 return _allocation_stats.prevSweep();
227 }
228 void set_prevSweep(ssize_t v) {
229 assert_proper_lock_protection();
230 _allocation_stats.set_prevSweep(v);
231 }
232 ssize_t beforeSweep() const {
233 return _allocation_stats.beforeSweep();
234 }
235 void set_beforeSweep(ssize_t v) {
236 assert_proper_lock_protection();
237 _allocation_stats.set_beforeSweep(v);
238 }
240 ssize_t coalBirths() const {
241 return _allocation_stats.coalBirths();
242 }
243 void set_coalBirths(ssize_t v) {
244 assert_proper_lock_protection();
245 _allocation_stats.set_coalBirths(v);
246 }
247 void increment_coalBirths() {
248 assert_proper_lock_protection();
249 _allocation_stats.increment_coalBirths();
250 }
252 ssize_t coalDeaths() const {
253 return _allocation_stats.coalDeaths();
254 }
255 void set_coalDeaths(ssize_t v) {
256 assert_proper_lock_protection();
257 _allocation_stats.set_coalDeaths(v);
258 }
259 void increment_coalDeaths() {
260 assert_proper_lock_protection();
261 _allocation_stats.increment_coalDeaths();
262 }
264 ssize_t splitBirths() const {
265 return _allocation_stats.splitBirths();
266 }
267 void set_splitBirths(ssize_t v) {
268 assert_proper_lock_protection();
269 _allocation_stats.set_splitBirths(v);
270 }
271 void increment_splitBirths() {
272 assert_proper_lock_protection();
273 _allocation_stats.increment_splitBirths();
274 }
276 ssize_t splitDeaths() const {
277 return _allocation_stats.splitDeaths();
278 }
279 void set_splitDeaths(ssize_t v) {
280 assert_proper_lock_protection();
281 _allocation_stats.set_splitDeaths(v);
282 }
283 void increment_splitDeaths() {
284 assert_proper_lock_protection();
285 _allocation_stats.increment_splitDeaths();
286 }
288 NOT_PRODUCT(
289 // For debugging. The "_returnedBytes" in all the lists are summed
290 // and compared with the total number of bytes swept during a
291 // collection.
292 size_t returnedBytes() const { return _allocation_stats.returnedBytes(); }
293 void set_returnedBytes(size_t v) { _allocation_stats.set_returnedBytes(v); }
294 void increment_returnedBytes_by(size_t v) {
295 _allocation_stats.set_returnedBytes(_allocation_stats.returnedBytes() + v);
296 }
297 )
299 // Unlink head of list and return it. Returns NULL if
300 // the list is empty.
301 FreeChunk* getChunkAtHead();
303 // Remove the first "n" or "count", whichever is smaller, chunks from the
304 // list, setting "fl", which is required to be empty, to point to them.
305 void getFirstNChunksFromList(size_t n, FreeList* fl);
307 // Unlink this chunk from it's free list
308 void removeChunk(FreeChunk* fc);
310 // Add this chunk to this free list.
311 void returnChunkAtHead(FreeChunk* fc);
312 void returnChunkAtTail(FreeChunk* fc);
314 // Similar to returnChunk* but also records some diagnostic
315 // information.
316 void returnChunkAtHead(FreeChunk* fc, bool record_return);
317 void returnChunkAtTail(FreeChunk* fc, bool record_return);
319 // Prepend "fl" (whose size is required to be the same as that of "this")
320 // to the front of "this" list.
321 void prepend(FreeList* fl);
323 // Verify that the chunk is in the list.
324 // found. Return NULL if "fc" is not found.
325 bool verifyChunkInFreeLists(FreeChunk* fc) const;
327 // Stats verification
328 void verify_stats() const PRODUCT_RETURN;
330 // Printing support
331 static void print_labels_on(outputStream* st, const char* c);
332 void print_on(outputStream* st, const char* c = NULL) const;
333 };
335 #endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP