Mercurial > hg > truffle
comparison src/share/vm/memory/permGen.cpp @ 480:d249b360e026
6782457: CMS: Livelock in CompactibleFreeListSpace::block_size()
6736295: SIGSEGV in product jvm, assertion "these are the only valid states during a mark sweep" in fastdebug
Summary: Restructured the code in the perm gen allocation retry loop so as to avoid "safepoint-blocking" on locks, in this case the Heap_lock, while holding uninitialized allocated heap storage.
Reviewed-by: apetrusenko, iveresov, jcoomes, jmasa, poonam
author | ysr |
---|---|
date | Wed, 10 Dec 2008 23:46:10 -0800 |
parents | d1605aabd0a1 |
children | 0fbdb4381b99 |
comparison
equal
deleted
inserted
replaced
464:8a0c882e46d6 | 480:d249b360e026 |
---|---|
24 | 24 |
25 #include "incls/_precompiled.incl" | 25 #include "incls/_precompiled.incl" |
26 #include "incls/_permGen.cpp.incl" | 26 #include "incls/_permGen.cpp.incl" |
27 | 27 |
28 HeapWord* PermGen::mem_allocate_in_gen(size_t size, Generation* gen) { | 28 HeapWord* PermGen::mem_allocate_in_gen(size_t size, Generation* gen) { |
29 MutexLocker ml(Heap_lock); | |
30 GCCause::Cause next_cause = GCCause::_permanent_generation_full; | 29 GCCause::Cause next_cause = GCCause::_permanent_generation_full; |
31 GCCause::Cause prev_cause = GCCause::_no_gc; | 30 GCCause::Cause prev_cause = GCCause::_no_gc; |
31 unsigned int gc_count_before, full_gc_count_before; | |
32 HeapWord* obj; | |
32 | 33 |
33 for (;;) { | 34 for (;;) { |
34 HeapWord* obj = gen->allocate(size, false); | 35 { |
35 if (obj != NULL) { | 36 MutexLocker ml(Heap_lock); |
36 return obj; | 37 if ((obj = gen->allocate(size, false)) != NULL) { |
37 } | 38 return obj; |
38 if (gen->capacity() < _capacity_expansion_limit || | 39 } |
39 prev_cause != GCCause::_no_gc) { | 40 if (gen->capacity() < _capacity_expansion_limit || |
40 obj = gen->expand_and_allocate(size, false); | 41 prev_cause != GCCause::_no_gc) { |
41 } | 42 obj = gen->expand_and_allocate(size, false); |
42 if (obj == NULL && prev_cause != GCCause::_last_ditch_collection) { | 43 } |
44 if (obj != NULL || prev_cause == GCCause::_last_ditch_collection) { | |
45 return obj; | |
46 } | |
43 if (GC_locker::is_active_and_needs_gc()) { | 47 if (GC_locker::is_active_and_needs_gc()) { |
44 // If this thread is not in a jni critical section, we stall | 48 // If this thread is not in a jni critical section, we stall |
45 // the requestor until the critical section has cleared and | 49 // the requestor until the critical section has cleared and |
46 // GC allowed. When the critical section clears, a GC is | 50 // GC allowed. When the critical section clears, a GC is |
47 // initiated by the last thread exiting the critical section; so | 51 // initiated by the last thread exiting the critical section; so |
59 " in jni critical section"); | 63 " in jni critical section"); |
60 } | 64 } |
61 return NULL; | 65 return NULL; |
62 } | 66 } |
63 } | 67 } |
68 // Read the GC count while holding the Heap_lock | |
69 gc_count_before = SharedHeap::heap()->total_collections(); | |
70 full_gc_count_before = SharedHeap::heap()->total_full_collections(); | |
71 } | |
64 | 72 |
65 // Read the GC count while holding the Heap_lock | 73 // Give up heap lock above, VMThread::execute below gets it back |
66 unsigned int gc_count_before = SharedHeap::heap()->total_collections(); | 74 VM_GenCollectForPermanentAllocation op(size, gc_count_before, full_gc_count_before, |
67 unsigned int full_gc_count_before = SharedHeap::heap()->total_full_collections(); | 75 next_cause); |
68 { | 76 VMThread::execute(&op); |
69 MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back | 77 if (!op.prologue_succeeded() || op.gc_locked()) { |
70 VM_GenCollectForPermanentAllocation op(size, gc_count_before, full_gc_count_before, | 78 assert(op.result() == NULL, "must be NULL if gc_locked() is true"); |
71 next_cause); | 79 continue; // retry and/or stall as necessary |
72 VMThread::execute(&op); | 80 } |
73 if (!op.prologue_succeeded() || op.gc_locked()) { | 81 obj = op.result(); |
74 assert(op.result() == NULL, "must be NULL if gc_locked() is true"); | 82 assert(obj == NULL || SharedHeap::heap()->is_in_reserved(obj), |
75 continue; // retry and/or stall as necessary | 83 "result not in heap"); |
76 } | 84 if (obj != NULL) { |
77 obj = op.result(); | |
78 assert(obj == NULL || SharedHeap::heap()->is_in_reserved(obj), | |
79 "result not in heap"); | |
80 if (obj != NULL) { | |
81 return obj; | |
82 } | |
83 } | |
84 prev_cause = next_cause; | |
85 next_cause = GCCause::_last_ditch_collection; | |
86 } else { | |
87 return obj; | 85 return obj; |
88 } | 86 } |
87 prev_cause = next_cause; | |
88 next_cause = GCCause::_last_ditch_collection; | |
89 } | 89 } |
90 } | 90 } |
91 | 91 |
92 CompactingPermGen::CompactingPermGen(ReservedSpace rs, | 92 CompactingPermGen::CompactingPermGen(ReservedSpace rs, |
93 ReservedSpace shared_rs, | 93 ReservedSpace shared_rs, |