Mercurial > hg > truffle
annotate src/share/vm/memory/freeList.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | 7baf47cb97cb |
children | 7848fc12602b |
rev | line source |
---|---|
0 | 1 /* |
17753
191174b49bec
8035406: Improve data structure for Code Cache remembered sets
tschatzl
parents:
17467
diff
changeset
|
2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
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 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
6026 | 26 #include "memory/freeBlockDictionary.hpp" |
27 #include "memory/freeList.hpp" | |
6885 | 28 #include "memory/metachunk.hpp" |
1972 | 29 #include "memory/sharedHeap.hpp" |
30 #include "runtime/globals.hpp" | |
31 #include "runtime/mutex.hpp" | |
32 #include "runtime/vmThread.hpp" | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6885
diff
changeset
|
33 #include "utilities/macros.hpp" |
0 | 34 |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6885
diff
changeset
|
35 #if INCLUDE_ALL_GCS |
6026 | 36 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6885
diff
changeset
|
37 #endif // INCLUDE_ALL_GCS |
6026 | 38 |
0 | 39 // Free list. A FreeList is used to access a linked list of chunks |
40 // of space in the heap. The head and tail are maintained so that | |
41 // items can be (as in the current implementation) added at the | |
42 // at the tail of the list and removed from the head of the list to | |
43 // maintain a FIFO queue. | |
44 | |
6026 | 45 template <class Chunk> |
46 FreeList<Chunk>::FreeList() : | |
0 | 47 _head(NULL), _tail(NULL) |
48 #ifdef ASSERT | |
49 , _protecting_lock(NULL) | |
50 #endif | |
51 { | |
52 _size = 0; | |
53 _count = 0; | |
54 } | |
55 | |
6026 | 56 template <class Chunk> |
6885 | 57 void FreeList<Chunk>::link_head(Chunk* v) { |
58 assert_proper_lock_protection(); | |
59 set_head(v); | |
60 // If this method is not used (just set the head instead), | |
61 // this check can be avoided. | |
62 if (v != NULL) { | |
63 v->link_prev(NULL); | |
64 } | |
65 } | |
66 | |
67 | |
68 | |
69 template <class Chunk> | |
70 void FreeList<Chunk>::reset() { | |
71 // Don't set the _size to 0 because this method is | |
72 // used with a existing list that has a size but which has | |
73 // been emptied. | |
74 // Don't clear the _protecting_lock of an existing list. | |
0 | 75 set_count(0); |
76 set_head(NULL); | |
77 set_tail(NULL); | |
78 } | |
79 | |
6026 | 80 template <class Chunk> |
6885 | 81 void FreeList<Chunk>::initialize() { |
82 #ifdef ASSERT | |
83 // Needed early because it might be checked in other initializing code. | |
84 set_protecting_lock(NULL); | |
85 #endif | |
86 reset(); | |
87 set_size(0); | |
0 | 88 } |
89 | |
6885 | 90 template <class Chunk_t> |
91 Chunk_t* FreeList<Chunk_t>::get_chunk_at_head() { | |
0 | 92 assert_proper_lock_protection(); |
93 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
94 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
6885 | 95 Chunk_t* fc = head(); |
0 | 96 if (fc != NULL) { |
6885 | 97 Chunk_t* nextFC = fc->next(); |
0 | 98 if (nextFC != NULL) { |
99 // The chunk fc being removed has a "next". Set the "next" to the | |
100 // "prev" of fc. | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
101 nextFC->link_prev(NULL); |
0 | 102 } else { // removed tail of list |
103 link_tail(NULL); | |
104 } | |
105 link_head(nextFC); | |
106 decrement_count(); | |
107 } | |
108 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
109 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
110 return fc; | |
111 } | |
112 | |
113 | |
6026 | 114 template <class Chunk> |
115 void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) { | |
0 | 116 assert_proper_lock_protection(); |
117 assert(fl->count() == 0, "Precondition"); | |
118 if (count() > 0) { | |
119 int k = 1; | |
120 fl->set_head(head()); n--; | |
6026 | 121 Chunk* tl = head(); |
0 | 122 while (tl->next() != NULL && n > 0) { |
123 tl = tl->next(); n--; k++; | |
124 } | |
125 assert(tl != NULL, "Loop Inv."); | |
126 | |
127 // First, fix up the list we took from. | |
6026 | 128 Chunk* new_head = tl->next(); |
0 | 129 set_head(new_head); |
130 set_count(count() - k); | |
131 if (new_head == NULL) { | |
132 set_tail(NULL); | |
133 } else { | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
134 new_head->link_prev(NULL); |
0 | 135 } |
136 // Now we can fix up the tail. | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
137 tl->link_next(NULL); |
0 | 138 // And return the result. |
139 fl->set_tail(tl); | |
140 fl->set_count(k); | |
141 } | |
142 } | |
143 | |
144 // Remove this chunk from the list | |
6026 | 145 template <class Chunk> |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
146 void FreeList<Chunk>::remove_chunk(Chunk*fc) { |
0 | 147 assert_proper_lock_protection(); |
148 assert(head() != NULL, "Remove from empty list"); | |
149 assert(fc != NULL, "Remove a NULL chunk"); | |
150 assert(size() == fc->size(), "Wrong list"); | |
151 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
152 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
153 | |
6026 | 154 Chunk* prevFC = fc->prev(); |
155 Chunk* nextFC = fc->next(); | |
0 | 156 if (nextFC != NULL) { |
157 // The chunk fc being removed has a "next". Set the "next" to the | |
158 // "prev" of fc. | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
159 nextFC->link_prev(prevFC); |
0 | 160 } else { // removed tail of list |
161 link_tail(prevFC); | |
162 } | |
163 if (prevFC == NULL) { // removed head of list | |
164 link_head(nextFC); | |
165 assert(nextFC == NULL || nextFC->prev() == NULL, | |
166 "Prev of head should be NULL"); | |
167 } else { | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
168 prevFC->link_next(nextFC); |
0 | 169 assert(tail() != prevFC || prevFC->next() == NULL, |
170 "Next of tail should be NULL"); | |
171 } | |
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 | 175 // clear next and prev fields of fc, debug only |
176 NOT_PRODUCT( | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
177 fc->link_prev(NULL); |
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
178 fc->link_next(NULL); |
0 | 179 ) |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
180 assert(fc->is_free(), "Should still be a free chunk"); |
0 | 181 assert(head() == NULL || head()->prev() == NULL, "list invariant"); |
182 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
183 assert(head() == NULL || head()->size() == size(), "wrong item on list"); | |
184 assert(tail() == NULL || tail()->size() == size(), "wrong item on list"); | |
185 } | |
186 | |
187 // Add this chunk at the head of the list. | |
6026 | 188 template <class Chunk> |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
189 void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk, bool record_return) { |
0 | 190 assert_proper_lock_protection(); |
191 assert(chunk != NULL, "insert a NULL chunk"); | |
192 assert(size() == chunk->size(), "Wrong size"); | |
193 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
194 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
195 | |
6026 | 196 Chunk* oldHead = head(); |
0 | 197 assert(chunk != oldHead, "double insertion"); |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
198 chunk->link_after(oldHead); |
0 | 199 link_head(chunk); |
200 if (oldHead == NULL) { // only chunk in list | |
201 assert(tail() == NULL, "inconsistent FreeList"); | |
202 link_tail(chunk); | |
203 } | |
204 increment_count(); // of # of chunks in list | |
205 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
206 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
207 assert(head() == NULL || head()->size() == size(), "wrong item on list"); | |
208 assert(tail() == NULL || tail()->size() == size(), "wrong item on list"); | |
209 } | |
210 | |
6026 | 211 template <class Chunk> |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
212 void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk) { |
0 | 213 assert_proper_lock_protection(); |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
214 return_chunk_at_head(chunk, true); |
0 | 215 } |
216 | |
217 // Add this chunk at the tail of the list. | |
6026 | 218 template <class Chunk> |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
219 void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk, bool record_return) { |
0 | 220 assert_proper_lock_protection(); |
221 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
222 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
223 assert(chunk != NULL, "insert a NULL chunk"); | |
224 assert(size() == chunk->size(), "wrong size"); | |
225 | |
6026 | 226 Chunk* oldTail = tail(); |
0 | 227 assert(chunk != oldTail, "double insertion"); |
228 if (oldTail != NULL) { | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
229 oldTail->link_after(chunk); |
0 | 230 } else { // only chunk in list |
231 assert(head() == NULL, "inconsistent FreeList"); | |
232 link_head(chunk); | |
233 } | |
234 link_tail(chunk); | |
235 increment_count(); // of # of chunks in list | |
236 assert(head() == NULL || head()->prev() == NULL, "list invariant"); | |
237 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); | |
238 assert(head() == NULL || head()->size() == size(), "wrong item on list"); | |
239 assert(tail() == NULL || tail()->size() == size(), "wrong item on list"); | |
240 } | |
241 | |
6026 | 242 template <class Chunk> |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
243 void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk) { |
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
244 return_chunk_at_tail(chunk, true); |
0 | 245 } |
246 | |
6026 | 247 template <class Chunk> |
248 void FreeList<Chunk>::prepend(FreeList<Chunk>* fl) { | |
0 | 249 assert_proper_lock_protection(); |
250 if (fl->count() > 0) { | |
251 if (count() == 0) { | |
252 set_head(fl->head()); | |
253 set_tail(fl->tail()); | |
254 set_count(fl->count()); | |
255 } else { | |
256 // Both are non-empty. | |
6026 | 257 Chunk* fl_tail = fl->tail(); |
258 Chunk* this_head = head(); | |
0 | 259 assert(fl_tail->next() == NULL, "Well-formedness of fl"); |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
260 fl_tail->link_next(this_head); |
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
261 this_head->link_prev(fl_tail); |
0 | 262 set_head(fl->head()); |
263 set_count(count() + fl->count()); | |
264 } | |
265 fl->set_head(NULL); | |
266 fl->set_tail(NULL); | |
267 fl->set_count(0); | |
268 } | |
269 } | |
270 | |
6885 | 271 // verify_chunk_in_free_lists() is used to verify that an item is in this free list. |
0 | 272 // It is used as a debugging aid. |
6026 | 273 template <class Chunk> |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
6026
diff
changeset
|
274 bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const { |
0 | 275 // This is an internal consistency check, not part of the check that the |
276 // chunk is in the free lists. | |
277 guarantee(fc->size() == size(), "Wrong list is being searched"); | |
6026 | 278 Chunk* curFC = head(); |
0 | 279 while (curFC) { |
280 // This is an internal consistency check. | |
281 guarantee(size() == curFC->size(), "Chunk is in wrong list."); | |
282 if (fc == curFC) { | |
283 return true; | |
284 } | |
285 curFC = curFC->next(); | |
286 } | |
287 return false; | |
288 } | |
289 | |
290 #ifndef PRODUCT | |
6026 | 291 template <class Chunk> |
292 void FreeList<Chunk>::assert_proper_lock_protection_work() const { | |
6885 | 293 assert(protecting_lock() != NULL, "Don't call this directly"); |
1145
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
294 assert(ParallelGCThreads > 0, "Don't call this directly"); |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
295 Thread* thr = Thread::current(); |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
296 if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) { |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
297 // assert that we are holding the freelist lock |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
298 } else if (thr->is_GC_task_thread()) { |
6885 | 299 assert(protecting_lock()->owned_by_self(), "FreeList RACE DETECTED"); |
1145
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
300 } else if (thr->is_Java_thread()) { |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
301 assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing"); |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
302 } else { |
e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
ysr
parents:
196
diff
changeset
|
303 ShouldNotReachHere(); // unaccounted thread type? |
0 | 304 } |
305 } | |
306 #endif | |
12
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
307 |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
308 // Print the "label line" for free list stats. |
6026 | 309 template <class Chunk> |
310 void FreeList<Chunk>::print_labels_on(outputStream* st, const char* c) { | |
12
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
311 st->print("%16s\t", c); |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
312 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
|
313 "%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t" "\n", |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
314 "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep", |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
315 "count", "cBirths", "cDeaths", "sBirths", "sDeaths"); |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
316 } |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
317 |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
318 // 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
|
319 // 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
|
320 // 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
|
321 // (free list) block is printed in the first column. |
6885 | 322 template <class Chunk_t> |
323 void FreeList<Chunk_t>::print_on(outputStream* st, const char* c) const { | |
12
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
324 if (c != NULL) { |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
325 st->print("%16s", c); |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
326 } else { |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
327 st->print(SIZE_FORMAT_W(16), size()); |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
328 } |
6432c3bb6240
6668743: CMS: Consolidate block statistics reporting code
ysr
parents:
0
diff
changeset
|
329 } |
6026 | 330 |
6885 | 331 template class FreeList<Metablock>; |
332 template class FreeList<Metachunk>; | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6885
diff
changeset
|
333 #if INCLUDE_ALL_GCS |
6026 | 334 template class FreeList<FreeChunk>; |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6885
diff
changeset
|
335 #endif // INCLUDE_ALL_GCS |