comparison src/share/vm/memory/freeList.cpp @ 6885:685df3c6f84b

7045397: NPG: Add freelists to class loader arenas. Reviewed-by: coleenp, stefank, jprovino, ohair
author jmasa
date Tue, 18 Sep 2012 23:35:42 -0700
parents b9a9ed0f8eeb
children db9981fd3124
comparison
equal deleted inserted replaced
6877:d0e7716b179e 6885:685df3c6f84b
23 */ 23 */
24 24
25 #include "precompiled.hpp" 25 #include "precompiled.hpp"
26 #include "memory/freeBlockDictionary.hpp" 26 #include "memory/freeBlockDictionary.hpp"
27 #include "memory/freeList.hpp" 27 #include "memory/freeList.hpp"
28 #include "memory/metablock.hpp"
29 #include "memory/metachunk.hpp"
28 #include "memory/sharedHeap.hpp" 30 #include "memory/sharedHeap.hpp"
29 #include "runtime/globals.hpp" 31 #include "runtime/globals.hpp"
30 #include "runtime/mutex.hpp" 32 #include "runtime/mutex.hpp"
31 #include "runtime/vmThread.hpp" 33 #include "runtime/vmThread.hpp"
32 34
47 , _protecting_lock(NULL) 49 , _protecting_lock(NULL)
48 #endif 50 #endif
49 { 51 {
50 _size = 0; 52 _size = 0;
51 _count = 0; 53 _count = 0;
52 _hint = 0;
53 init_statistics();
54 } 54 }
55 55
56 template <class Chunk> 56 template <class Chunk>
57 FreeList<Chunk>::FreeList(Chunk* fc) : 57 FreeList<Chunk>::FreeList(Chunk* fc) :
58 _head(fc), _tail(fc) 58 _head(fc), _tail(fc)
60 , _protecting_lock(NULL) 60 , _protecting_lock(NULL)
61 #endif 61 #endif
62 { 62 {
63 _size = fc->size(); 63 _size = fc->size();
64 _count = 1; 64 _count = 1;
65 _hint = 0; 65 }
66 init_statistics(); 66
67 #ifndef PRODUCT 67 template <class Chunk>
68 _allocation_stats.set_returned_bytes(size() * HeapWordSize); 68 void FreeList<Chunk>::link_head(Chunk* v) {
69 #endif 69 assert_proper_lock_protection();
70 } 70 set_head(v);
71 71 // If this method is not used (just set the head instead),
72 template <class Chunk> 72 // this check can be avoided.
73 void FreeList<Chunk>::reset(size_t hint) { 73 if (v != NULL) {
74 v->link_prev(NULL);
75 }
76 }
77
78
79
80 template <class Chunk>
81 void FreeList<Chunk>::reset() {
82 // Don't set the _size to 0 because this method is
83 // used with a existing list that has a size but which has
84 // been emptied.
85 // Don't clear the _protecting_lock of an existing list.
74 set_count(0); 86 set_count(0);
75 set_head(NULL); 87 set_head(NULL);
76 set_tail(NULL); 88 set_tail(NULL);
77 set_hint(hint); 89 }
78 } 90
79 91 template <class Chunk>
80 template <class Chunk> 92 void FreeList<Chunk>::initialize() {
81 void FreeList<Chunk>::init_statistics(bool split_birth) { 93 #ifdef ASSERT
82 _allocation_stats.initialize(split_birth); 94 // Needed early because it might be checked in other initializing code.
83 } 95 set_protecting_lock(NULL);
84 96 #endif
85 template <class Chunk> 97 reset();
86 Chunk* FreeList<Chunk>::get_chunk_at_head() { 98 set_size(0);
87 assert_proper_lock_protection(); 99 }
88 assert(head() == NULL || head()->prev() == NULL, "list invariant"); 100
89 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); 101 template <class Chunk_t>
90 Chunk* fc = head(); 102 Chunk_t* FreeList<Chunk_t>::get_chunk_at_head() {
103 assert_proper_lock_protection();
104 assert(head() == NULL || head()->prev() == NULL, "list invariant");
105 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
106 Chunk_t* fc = head();
91 if (fc != NULL) { 107 if (fc != NULL) {
92 Chunk* nextFC = fc->next(); 108 Chunk_t* nextFC = fc->next();
93 if (nextFC != NULL) { 109 if (nextFC != NULL) {
94 // The chunk fc being removed has a "next". Set the "next" to the 110 // The chunk fc being removed has a "next". Set the "next" to the
95 // "prev" of fc. 111 // "prev" of fc.
96 nextFC->link_prev(NULL); 112 nextFC->link_prev(NULL);
97 } else { // removed tail of list 113 } else { // removed tail of list
195 if (oldHead == NULL) { // only chunk in list 211 if (oldHead == NULL) { // only chunk in list
196 assert(tail() == NULL, "inconsistent FreeList"); 212 assert(tail() == NULL, "inconsistent FreeList");
197 link_tail(chunk); 213 link_tail(chunk);
198 } 214 }
199 increment_count(); // of # of chunks in list 215 increment_count(); // of # of chunks in list
200 DEBUG_ONLY(
201 if (record_return) {
202 increment_returned_bytes_by(size()*HeapWordSize);
203 }
204 )
205 assert(head() == NULL || head()->prev() == NULL, "list invariant"); 216 assert(head() == NULL || head()->prev() == NULL, "list invariant");
206 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); 217 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
207 assert(head() == NULL || head()->size() == size(), "wrong item on list"); 218 assert(head() == NULL || head()->size() == size(), "wrong item on list");
208 assert(tail() == NULL || tail()->size() == size(), "wrong item on list"); 219 assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
209 } 220 }
231 assert(head() == NULL, "inconsistent FreeList"); 242 assert(head() == NULL, "inconsistent FreeList");
232 link_head(chunk); 243 link_head(chunk);
233 } 244 }
234 link_tail(chunk); 245 link_tail(chunk);
235 increment_count(); // of # of chunks in list 246 increment_count(); // of # of chunks in list
236 DEBUG_ONLY(
237 if (record_return) {
238 increment_returned_bytes_by(size()*HeapWordSize);
239 }
240 )
241 assert(head() == NULL || head()->prev() == NULL, "list invariant"); 247 assert(head() == NULL || head()->prev() == NULL, "list invariant");
242 assert(tail() == NULL || tail()->next() == NULL, "list invariant"); 248 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
243 assert(head() == NULL || head()->size() == size(), "wrong item on list"); 249 assert(head() == NULL || head()->size() == size(), "wrong item on list");
244 assert(tail() == NULL || tail()->size() == size(), "wrong item on list"); 250 assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
245 } 251 }
271 fl->set_tail(NULL); 277 fl->set_tail(NULL);
272 fl->set_count(0); 278 fl->set_count(0);
273 } 279 }
274 } 280 }
275 281
276 // verify_chunk_in_free_list() is used to verify that an item is in this free list. 282 // verify_chunk_in_free_lists() is used to verify that an item is in this free list.
277 // It is used as a debugging aid. 283 // It is used as a debugging aid.
278 template <class Chunk> 284 template <class Chunk>
279 bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const { 285 bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
280 // This is an internal consistency check, not part of the check that the 286 // This is an internal consistency check, not part of the check that the
281 // chunk is in the free lists. 287 // chunk is in the free lists.
292 return false; 298 return false;
293 } 299 }
294 300
295 #ifndef PRODUCT 301 #ifndef PRODUCT
296 template <class Chunk> 302 template <class Chunk>
297 void FreeList<Chunk>::verify_stats() const {
298 // The +1 of the LH comparand is to allow some "looseness" in
299 // checking: we usually call this interface when adding a block
300 // and we'll subsequently update the stats; we cannot update the
301 // stats beforehand because in the case of the large-block BT
302 // dictionary for example, this might be the first block and
303 // in that case there would be no place that we could record
304 // the stats (which are kept in the block itself).
305 assert((_allocation_stats.prev_sweep() + _allocation_stats.split_births()
306 + _allocation_stats.coal_births() + 1) // Total Production Stock + 1
307 >= (_allocation_stats.split_deaths() + _allocation_stats.coal_deaths()
308 + (ssize_t)count()), // Total Current Stock + depletion
309 err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
310 " violates Conservation Principle: "
311 "prev_sweep(" SIZE_FORMAT ")"
312 " + split_births(" SIZE_FORMAT ")"
313 " + coal_births(" SIZE_FORMAT ") + 1 >= "
314 " split_deaths(" SIZE_FORMAT ")"
315 " coal_deaths(" SIZE_FORMAT ")"
316 " + count(" SSIZE_FORMAT ")",
317 this, _size, _allocation_stats.prev_sweep(), _allocation_stats.split_births(),
318 _allocation_stats.split_births(), _allocation_stats.split_deaths(),
319 _allocation_stats.coal_deaths(), count()));
320 }
321
322 template <class Chunk>
323 void FreeList<Chunk>::assert_proper_lock_protection_work() const { 303 void FreeList<Chunk>::assert_proper_lock_protection_work() const {
324 assert(_protecting_lock != NULL, "Don't call this directly"); 304 assert(protecting_lock() != NULL, "Don't call this directly");
325 assert(ParallelGCThreads > 0, "Don't call this directly"); 305 assert(ParallelGCThreads > 0, "Don't call this directly");
326 Thread* thr = Thread::current(); 306 Thread* thr = Thread::current();
327 if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) { 307 if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
328 // assert that we are holding the freelist lock 308 // assert that we are holding the freelist lock
329 } else if (thr->is_GC_task_thread()) { 309 } else if (thr->is_GC_task_thread()) {
330 assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED"); 310 assert(protecting_lock()->owned_by_self(), "FreeList RACE DETECTED");
331 } else if (thr->is_Java_thread()) { 311 } else if (thr->is_Java_thread()) {
332 assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing"); 312 assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
333 } else { 313 } else {
334 ShouldNotReachHere(); // unaccounted thread type? 314 ShouldNotReachHere(); // unaccounted thread type?
335 } 315 }
348 328
349 // Print the AllocationStats for the given free list. If the second argument 329 // Print the AllocationStats for the given free list. If the second argument
350 // to the call is a non-null string, it is printed in the first column; 330 // to the call is a non-null string, it is printed in the first column;
351 // otherwise, if the argument is null (the default), then the size of the 331 // otherwise, if the argument is null (the default), then the size of the
352 // (free list) block is printed in the first column. 332 // (free list) block is printed in the first column.
353 template <class Chunk> 333 template <class Chunk_t>
354 void FreeList<Chunk>::print_on(outputStream* st, const char* c) const { 334 void FreeList<Chunk_t>::print_on(outputStream* st, const char* c) const {
355 if (c != NULL) { 335 if (c != NULL) {
356 st->print("%16s", c); 336 st->print("%16s", c);
357 } else { 337 } else {
358 st->print(SIZE_FORMAT_W(16), size()); 338 st->print(SIZE_FORMAT_W(16), size());
359 } 339 }
360 st->print("\t" 340 }
361 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" 341
362 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", 342 template class FreeList<Metablock>;
363 bfr_surp(), surplus(), desired(), prev_sweep(), before_sweep(), 343 template class FreeList<Metachunk>;
364 count(), coal_births(), coal_deaths(), split_births(), split_deaths());
365 }
366
367 #ifndef SERIALGC 344 #ifndef SERIALGC
368 // Needs to be after the definitions have been seen.
369 template class FreeList<FreeChunk>; 345 template class FreeList<FreeChunk>;
370 #endif // SERIALGC 346 #endif // SERIALGC