annotate src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp @ 3285:49a67202bc67

7011855: G1: non-product flag to artificially grow the heap Summary: It introduces non-product cmd line parameter G1DummyRegionsPerGC which indicates how many "dummy" regions to allocate at the end of each GC. This allows the G1 heap to grow artificially and makes concurrent marking cycles more frequent irrespective of what the application that is running is doing. The dummy regions will be found totally empty during cleanup so this parameter can also be used to stress the concurrent cleanup operation. Reviewed-by: brutisso, johnc
author tonyp
date Tue, 19 Apr 2011 15:46:59 -0400
parents f95d63e2154a
children f75137faa7fe
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1145
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1145
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1145
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
26 #include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
27 #include "gc_implementation/concurrentMarkSweep/freeList.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
28 #include "memory/sharedHeap.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
29 #include "runtime/globals.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
30 #include "runtime/mutex.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1777
diff changeset
31 #include "runtime/vmThread.hpp"
0
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // Free list. A FreeList is used to access a linked list of chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // of space in the heap. The head and tail are maintained so that
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // items can be (as in the current implementation) added at the
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // at the tail of the list and removed from the head of the list to
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // maintain a FIFO queue.
a61af66fc99e Initial load
duke
parents:
diff changeset
38
a61af66fc99e Initial load
duke
parents:
diff changeset
39 FreeList::FreeList() :
a61af66fc99e Initial load
duke
parents:
diff changeset
40 _head(NULL), _tail(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
41 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
42 , _protecting_lock(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
43 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
44 {
a61af66fc99e Initial load
duke
parents:
diff changeset
45 _size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
46 _count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
47 _hint = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
48 init_statistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
49 }
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 FreeList::FreeList(FreeChunk* fc) :
a61af66fc99e Initial load
duke
parents:
diff changeset
52 _head(fc), _tail(fc)
a61af66fc99e Initial load
duke
parents:
diff changeset
53 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
54 , _protecting_lock(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
55 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
56 {
a61af66fc99e Initial load
duke
parents:
diff changeset
57 _size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
58 _count = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
59 _hint = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
60 init_statistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
61 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
62 _allocation_stats.set_returnedBytes(size() * HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
63 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
64 }
a61af66fc99e Initial load
duke
parents:
diff changeset
65
a61af66fc99e Initial load
duke
parents:
diff changeset
66 FreeList::FreeList(HeapWord* addr, size_t size) :
a61af66fc99e Initial load
duke
parents:
diff changeset
67 _head((FreeChunk*) addr), _tail((FreeChunk*) addr)
a61af66fc99e Initial load
duke
parents:
diff changeset
68 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
69 , _protecting_lock(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
70 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
71 {
a61af66fc99e Initial load
duke
parents:
diff changeset
72 assert(size > sizeof(FreeChunk), "size is too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
73 head()->setSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
74 _size = size;
a61af66fc99e Initial load
duke
parents:
diff changeset
75 _count = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
76 init_statistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
77 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
78 _allocation_stats.set_returnedBytes(_size * HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
79 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
80 }
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 void FreeList::reset(size_t hint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
83 set_count(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
84 set_head(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
85 set_tail(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
86 set_hint(hint);
a61af66fc99e Initial load
duke
parents:
diff changeset
87 }
a61af66fc99e Initial load
duke
parents:
diff changeset
88
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
89 void FreeList::init_statistics(bool split_birth) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
90 _allocation_stats.initialize(split_birth);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
91 }
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93 FreeChunk* FreeList::getChunkAtHead() {
a61af66fc99e Initial load
duke
parents:
diff changeset
94 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
95 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
96 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
97 FreeChunk* fc = head();
a61af66fc99e Initial load
duke
parents:
diff changeset
98 if (fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
99 FreeChunk* nextFC = fc->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
100 if (nextFC != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // The chunk fc being removed has a "next". Set the "next" to the
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // "prev" of fc.
a61af66fc99e Initial load
duke
parents:
diff changeset
103 nextFC->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 } else { // removed tail of list
a61af66fc99e Initial load
duke
parents:
diff changeset
105 link_tail(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
107 link_head(nextFC);
a61af66fc99e Initial load
duke
parents:
diff changeset
108 decrement_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
110 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
111 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
112 return fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
114
a61af66fc99e Initial load
duke
parents:
diff changeset
115
a61af66fc99e Initial load
duke
parents:
diff changeset
116 void FreeList::getFirstNChunksFromList(size_t n, FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
117 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
118 assert(fl->count() == 0, "Precondition");
a61af66fc99e Initial load
duke
parents:
diff changeset
119 if (count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 int k = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 fl->set_head(head()); n--;
a61af66fc99e Initial load
duke
parents:
diff changeset
122 FreeChunk* tl = head();
a61af66fc99e Initial load
duke
parents:
diff changeset
123 while (tl->next() != NULL && n > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
124 tl = tl->next(); n--; k++;
a61af66fc99e Initial load
duke
parents:
diff changeset
125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
126 assert(tl != NULL, "Loop Inv.");
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // First, fix up the list we took from.
a61af66fc99e Initial load
duke
parents:
diff changeset
129 FreeChunk* new_head = tl->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
130 set_head(new_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
131 set_count(count() - k);
a61af66fc99e Initial load
duke
parents:
diff changeset
132 if (new_head == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 set_tail(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
134 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 new_head->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // Now we can fix up the tail.
a61af66fc99e Initial load
duke
parents:
diff changeset
138 tl->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
139 // And return the result.
a61af66fc99e Initial load
duke
parents:
diff changeset
140 fl->set_tail(tl);
a61af66fc99e Initial load
duke
parents:
diff changeset
141 fl->set_count(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // Remove this chunk from the list
a61af66fc99e Initial load
duke
parents:
diff changeset
146 void FreeList::removeChunk(FreeChunk*fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
148 assert(head() != NULL, "Remove from empty list");
a61af66fc99e Initial load
duke
parents:
diff changeset
149 assert(fc != NULL, "Remove a NULL chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
150 assert(size() == fc->size(), "Wrong list");
a61af66fc99e Initial load
duke
parents:
diff changeset
151 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
152 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
153
a61af66fc99e Initial load
duke
parents:
diff changeset
154 FreeChunk* prevFC = fc->prev();
a61af66fc99e Initial load
duke
parents:
diff changeset
155 FreeChunk* nextFC = fc->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
156 if (nextFC != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // The chunk fc being removed has a "next". Set the "next" to the
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // "prev" of fc.
a61af66fc99e Initial load
duke
parents:
diff changeset
159 nextFC->linkPrev(prevFC);
a61af66fc99e Initial load
duke
parents:
diff changeset
160 } else { // removed tail of list
a61af66fc99e Initial load
duke
parents:
diff changeset
161 link_tail(prevFC);
a61af66fc99e Initial load
duke
parents:
diff changeset
162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
163 if (prevFC == NULL) { // removed head of list
a61af66fc99e Initial load
duke
parents:
diff changeset
164 link_head(nextFC);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 assert(nextFC == NULL || nextFC->prev() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
166 "Prev of head should be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
167 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 prevFC->linkNext(nextFC);
a61af66fc99e Initial load
duke
parents:
diff changeset
169 assert(tail() != prevFC || prevFC->next() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
170 "Next of tail should be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
171 }
a61af66fc99e Initial load
duke
parents:
diff changeset
172 decrement_count();
1777
179464550c7d 6983930: CMS: Various small cleanups ca September 2010
ysr
parents: 1552
diff changeset
173 assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
179464550c7d 6983930: CMS: Various small cleanups ca September 2010
ysr
parents: 1552
diff changeset
174 "H/T/C Inconsistency");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // clear next and prev fields of fc, debug only
a61af66fc99e Initial load
duke
parents:
diff changeset
176 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
177 fc->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
178 fc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
179 )
a61af66fc99e Initial load
duke
parents:
diff changeset
180 assert(fc->isFree(), "Should still be a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
181 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
182 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
183 assert(head() == NULL || head()->size() == size(), "wrong item on list");
a61af66fc99e Initial load
duke
parents:
diff changeset
184 assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // Add this chunk at the head of the list.
a61af66fc99e Initial load
duke
parents:
diff changeset
188 void FreeList::returnChunkAtHead(FreeChunk* chunk, bool record_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
189 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
190 assert(chunk != NULL, "insert a NULL chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
191 assert(size() == chunk->size(), "Wrong size");
a61af66fc99e Initial load
duke
parents:
diff changeset
192 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
193 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 FreeChunk* oldHead = head();
a61af66fc99e Initial load
duke
parents:
diff changeset
196 assert(chunk != oldHead, "double insertion");
a61af66fc99e Initial load
duke
parents:
diff changeset
197 chunk->linkAfter(oldHead);
a61af66fc99e Initial load
duke
parents:
diff changeset
198 link_head(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
199 if (oldHead == NULL) { // only chunk in list
a61af66fc99e Initial load
duke
parents:
diff changeset
200 assert(tail() == NULL, "inconsistent FreeList");
a61af66fc99e Initial load
duke
parents:
diff changeset
201 link_tail(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203 increment_count(); // of # of chunks in list
a61af66fc99e Initial load
duke
parents:
diff changeset
204 DEBUG_ONLY(
a61af66fc99e Initial load
duke
parents:
diff changeset
205 if (record_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 increment_returnedBytes_by(size()*HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
207 }
a61af66fc99e Initial load
duke
parents:
diff changeset
208 )
a61af66fc99e Initial load
duke
parents:
diff changeset
209 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
210 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
211 assert(head() == NULL || head()->size() == size(), "wrong item on list");
a61af66fc99e Initial load
duke
parents:
diff changeset
212 assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
a61af66fc99e Initial load
duke
parents:
diff changeset
213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 void FreeList::returnChunkAtHead(FreeChunk* chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
216 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
217 returnChunkAtHead(chunk, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 // Add this chunk at the tail of the list.
a61af66fc99e Initial load
duke
parents:
diff changeset
221 void FreeList::returnChunkAtTail(FreeChunk* chunk, bool record_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
222 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
223 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
224 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
225 assert(chunk != NULL, "insert a NULL chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
226 assert(size() == chunk->size(), "wrong size");
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 FreeChunk* oldTail = tail();
a61af66fc99e Initial load
duke
parents:
diff changeset
229 assert(chunk != oldTail, "double insertion");
a61af66fc99e Initial load
duke
parents:
diff changeset
230 if (oldTail != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
231 oldTail->linkAfter(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
232 } else { // only chunk in list
a61af66fc99e Initial load
duke
parents:
diff changeset
233 assert(head() == NULL, "inconsistent FreeList");
a61af66fc99e Initial load
duke
parents:
diff changeset
234 link_head(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
236 link_tail(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
237 increment_count(); // of # of chunks in list
a61af66fc99e Initial load
duke
parents:
diff changeset
238 DEBUG_ONLY(
a61af66fc99e Initial load
duke
parents:
diff changeset
239 if (record_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 increment_returnedBytes_by(size()*HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
242 )
a61af66fc99e Initial load
duke
parents:
diff changeset
243 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
244 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
245 assert(head() == NULL || head()->size() == size(), "wrong item on list");
a61af66fc99e Initial load
duke
parents:
diff changeset
246 assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
a61af66fc99e Initial load
duke
parents:
diff changeset
247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
248
a61af66fc99e Initial load
duke
parents:
diff changeset
249 void FreeList::returnChunkAtTail(FreeChunk* chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
250 returnChunkAtTail(chunk, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252
a61af66fc99e Initial load
duke
parents:
diff changeset
253 void FreeList::prepend(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
254 assert_proper_lock_protection();
a61af66fc99e Initial load
duke
parents:
diff changeset
255 if (fl->count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 if (count() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
257 set_head(fl->head());
a61af66fc99e Initial load
duke
parents:
diff changeset
258 set_tail(fl->tail());
a61af66fc99e Initial load
duke
parents:
diff changeset
259 set_count(fl->count());
a61af66fc99e Initial load
duke
parents:
diff changeset
260 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // Both are non-empty.
a61af66fc99e Initial load
duke
parents:
diff changeset
262 FreeChunk* fl_tail = fl->tail();
a61af66fc99e Initial load
duke
parents:
diff changeset
263 FreeChunk* this_head = head();
a61af66fc99e Initial load
duke
parents:
diff changeset
264 assert(fl_tail->next() == NULL, "Well-formedness of fl");
a61af66fc99e Initial load
duke
parents:
diff changeset
265 fl_tail->linkNext(this_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
266 this_head->linkPrev(fl_tail);
a61af66fc99e Initial load
duke
parents:
diff changeset
267 set_head(fl->head());
a61af66fc99e Initial load
duke
parents:
diff changeset
268 set_count(count() + fl->count());
a61af66fc99e Initial load
duke
parents:
diff changeset
269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
270 fl->set_head(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
271 fl->set_tail(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
272 fl->set_count(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
275
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // verifyChunkInFreeLists() is used to verify that an item is in this free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // It is used as a debugging aid.
a61af66fc99e Initial load
duke
parents:
diff changeset
278 bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // This is an internal consistency check, not part of the check that the
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // chunk is in the free lists.
a61af66fc99e Initial load
duke
parents:
diff changeset
281 guarantee(fc->size() == size(), "Wrong list is being searched");
a61af66fc99e Initial load
duke
parents:
diff changeset
282 FreeChunk* curFC = head();
a61af66fc99e Initial load
duke
parents:
diff changeset
283 while (curFC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // This is an internal consistency check.
a61af66fc99e Initial load
duke
parents:
diff changeset
285 guarantee(size() == curFC->size(), "Chunk is in wrong list.");
a61af66fc99e Initial load
duke
parents:
diff changeset
286 if (fc == curFC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
287 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
289 curFC = curFC->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
291 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
293
a61af66fc99e Initial load
duke
parents:
diff changeset
294 #ifndef PRODUCT
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
295 void FreeList::verify_stats() const {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
296 // The +1 of the LH comparand is to allow some "looseness" in
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
297 // checking: we usually call this interface when adding a block
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
298 // and we'll subsequently update the stats; we cannot update the
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
299 // stats beforehand because in the case of the large-block BT
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
300 // dictionary for example, this might be the first block and
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
301 // in that case there would be no place that we could record
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
302 // the stats (which are kept in the block itself).
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
303 assert(_allocation_stats.prevSweep() + _allocation_stats.splitBirths() + 1 // Total Stock + 1
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
304 >= _allocation_stats.splitDeaths() + (ssize_t)count(), "Conservation Principle");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
305 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
306
0
a61af66fc99e Initial load
duke
parents:
diff changeset
307 void FreeList::assert_proper_lock_protection_work() const {
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
308 assert(_protecting_lock != NULL, "Don't call this directly");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
309 assert(ParallelGCThreads > 0, "Don't call this directly");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
310 Thread* thr = Thread::current();
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
311 if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
312 // assert that we are holding the freelist lock
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
313 } else if (thr->is_GC_task_thread()) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
314 assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
315 } else if (thr->is_Java_thread()) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
316 assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
317 } else {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 196
diff changeset
318 ShouldNotReachHere(); // unaccounted thread type?
0
a61af66fc99e Initial load
duke
parents:
diff changeset
319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
320 }
a61af66fc99e Initial load
duke
parents:
diff changeset
321 #endif
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
322
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
323 // Print the "label line" for free list stats.
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
324 void FreeList::print_labels_on(outputStream* st, const char* c) {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
325 st->print("%16s\t", c);
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
326 st->print("%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t"
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
327 "%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t" "\n",
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
328 "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
329 "count", "cBirths", "cDeaths", "sBirths", "sDeaths");
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
330 }
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
331
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
332 // Print the AllocationStats for the given free list. If the second argument
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
333 // to the call is a non-null string, it is printed in the first column;
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
334 // otherwise, if the argument is null (the default), then the size of the
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
335 // (free list) block is printed in the first column.
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
336 void FreeList::print_on(outputStream* st, const char* c) const {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
337 if (c != NULL) {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
338 st->print("%16s", c);
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
339 } else {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
340 st->print(SIZE_FORMAT_W(16), size());
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
341 }
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
342 st->print("\t"
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
343 SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
344 SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
345 bfrSurp(), surplus(), desired(), prevSweep(), beforeSweep(),
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
346 count(), coalBirths(), coalDeaths(), splitBirths(), splitDeaths());
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
347 }