Mercurial > hg > graal-jvmci-8
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 |