27 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
28 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
29 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
30 #include "gc_implementation/shared/gcTrace.hpp"
31 #include "gc_implementation/shared/mutableSpace.hpp"
32 #include "memory/allocation.inline.hpp"
33 #include "memory/memRegion.hpp"
34 #include "memory/padded.inline.hpp"
35 #include "oops/instanceKlass.inline.hpp"
36 #include "oops/instanceMirrorKlass.inline.hpp"
37 #include "oops/objArrayKlass.inline.hpp"
38 #include "oops/oop.inline.hpp"
39 #include "utilities/stack.inline.hpp"
40
41 PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL;
42 OopStarTaskQueueSet* PSPromotionManager::_stack_array_depth = NULL;
43 PSOldGen* PSPromotionManager::_old_gen = NULL;
44 MutableSpace* PSPromotionManager::_young_space = NULL;
45
46 void PSPromotionManager::initialize() {
47 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
48 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
49
50 _old_gen = heap->old_gen();
51 _young_space = heap->young_gen()->to_space();
52
53 // To prevent false sharing, we pad the PSPromotionManagers
54 // and make sure that the first instance starts at a cache line.
55 assert(_manager_array == NULL, "Attempt to initialize twice");
56 _manager_array = PaddedArray<PSPromotionManager, mtGC>::create_unfreeable(ParallelGCThreads + 1);
57 guarantee(_manager_array != NULL, "Could not initialize promotion manager");
58
59 _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads);
60 guarantee(_stack_array_depth != NULL, "Could not initialize promotion manager");
61
62 // Create and register the PSPromotionManager(s) for the worker threads.
63 for(uint i=0; i<ParallelGCThreads; i++) {
64 stack_array_depth()->register_queue(i, _manager_array[i].claimed_stack_depth());
65 }
66 // The VMThread gets its own PSPromotionManager, which is not available
67 // for work stealing.
68 }
71 // psScavenge.inline.hpp and psPromotionManager.inline.hpp.
72 bool PSPromotionManager::should_scavenge(oop* p, bool check_to_space) {
73 return PSScavenge::should_scavenge(p, check_to_space);
74 }
75 bool PSPromotionManager::should_scavenge(narrowOop* p, bool check_to_space) {
76 return PSScavenge::should_scavenge(p, check_to_space);
77 }
78
79 PSPromotionManager* PSPromotionManager::gc_thread_promotion_manager(int index) {
80 assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
81 assert(_manager_array != NULL, "Sanity");
82 return &_manager_array[index];
83 }
84
85 PSPromotionManager* PSPromotionManager::vm_thread_promotion_manager() {
86 assert(_manager_array != NULL, "Sanity");
87 return &_manager_array[ParallelGCThreads];
88 }
89
90 void PSPromotionManager::pre_scavenge() {
91 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
92 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
93
94 _young_space = heap->young_gen()->to_space();
95
96 for(uint i=0; i<ParallelGCThreads+1; i++) {
97 manager_array(i)->reset();
98 }
99 }
100
101 bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) {
102 bool promotion_failure_occurred = false;
103
104 TASKQUEUE_STATS_ONLY(if (PrintTaskqueue) print_taskqueue_stats());
105 for (uint i = 0; i < ParallelGCThreads + 1; i++) {
106 PSPromotionManager* manager = manager_array(i);
107 assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
108 if (manager->_promotion_failed_info.has_failed()) {
109 gc_tracer.report_promotion_failed(manager->_promotion_failed_info);
110 promotion_failure_occurred = true;
111 }
112 manager->flush_labs();
115 }
116
117 #if TASKQUEUE_STATS
118 void
119 PSPromotionManager::print_local_stats(outputStream* const out, uint i) const {
120 #define FMT " " SIZE_FORMAT_W(10)
121 out->print_cr("%3u" FMT FMT FMT FMT, i, _masked_pushes, _masked_steals,
122 _arrays_chunked, _array_chunks_processed);
123 #undef FMT
124 }
125
126 static const char* const pm_stats_hdr[] = {
127 " --------masked------- arrays array",
128 "thr push steal chunked chunks",
129 "--- ---------- ---------- ---------- ----------"
130 };
131
132 void
133 PSPromotionManager::print_taskqueue_stats(outputStream* const out) {
134 out->print_cr("== GC Tasks Stats, GC %3d",
135 Universe::heap()->total_collections());
136
137 TaskQueueStats totals;
138 out->print("thr "); TaskQueueStats::print_header(1, out); out->cr();
139 out->print("--- "); TaskQueueStats::print_header(2, out); out->cr();
140 for (uint i = 0; i < ParallelGCThreads + 1; ++i) {
141 TaskQueueStats& next = manager_array(i)->_claimed_stack_depth.stats;
142 out->print("%3d ", i); next.print(out); out->cr();
143 totals += next;
144 }
145 out->print("tot "); totals.print(out); out->cr();
146
147 const uint hlines = sizeof(pm_stats_hdr) / sizeof(pm_stats_hdr[0]);
148 for (uint i = 0; i < hlines; ++i) out->print_cr("%s", pm_stats_hdr[i]);
149 for (uint i = 0; i < ParallelGCThreads + 1; ++i) {
150 manager_array(i)->print_local_stats(out, i);
151 }
152 }
153
154 void
155 PSPromotionManager::reset_stats() {
156 claimed_stack_depth()->stats.reset();
157 _masked_pushes = _masked_steals = 0;
158 _arrays_chunked = _array_chunks_processed = 0;
159 }
160 #endif // TASKQUEUE_STATS
161
162 PSPromotionManager::PSPromotionManager() {
163 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
164 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
165
166 // We set the old lab's start array.
167 _old_lab.set_start_array(old_gen()->start_array());
168
169 uint queue_size;
170 claimed_stack_depth()->initialize();
171 queue_size = claimed_stack_depth()->max_elems();
172
173 _totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0);
174 if (_totally_drain) {
175 _target_stack_size = 0;
176 } else {
177 // don't let the target stack size to be more than 1/4 of the entries
178 _target_stack_size = (uint) MIN2((uint) GCDrainStackTargetSize,
179 (uint) (queue_size / 4));
180 }
181
182 _array_chunk_size = ParGCArrayScanChunk;
183 // let's choose 1.5x the chunk size
184 _min_array_size_for_chunking = 3 * _array_chunk_size / 2;
185
186 reset();
187 }
188
189 void PSPromotionManager::reset() {
190 assert(stacks_empty(), "reset of non-empty stack");
191
192 // We need to get an assert in here to make sure the labs are always flushed.
193
194 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
195 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
196
197 // Do not prefill the LAB's, save heap wastage!
198 HeapWord* lab_base = young_space()->top();
199 _young_lab.initialize(MemRegion(lab_base, (size_t)0));
200 _young_gen_is_full = false;
201
202 lab_base = old_gen()->object_space()->top();
203 _old_lab.initialize(MemRegion(lab_base, (size_t)0));
204 _old_gen_is_full = false;
205
206 _promotion_failed_info.reset();
207
208 TASKQUEUE_STATS_ONLY(reset_stats());
209 }
210
211
212 void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
213 totally_drain = totally_drain || _totally_drain;
214
215 #ifdef ASSERT
216 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
217 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
218 MutableSpace* to_space = heap->young_gen()->to_space();
219 MutableSpace* old_space = heap->old_gen()->object_space();
220 #endif /* ASSERT */
221
222 OopStarTaskQueue* const tq = claimed_stack_depth();
223 do {
224 StarTask p;
225
226 // Drain overflow stack first, so other threads can steal from
227 // claimed stack while we work.
228 while (tq->pop_overflow(p)) {
229 process_popped_location_depth(p);
230 }
231
232 if (totally_drain) {
233 while (tq->pop_local(p)) {
234 process_popped_location_depth(p);
235 }
236 } else {
237 while (tq->size() > _target_stack_size && tq->pop_local(p)) {
|
27 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
28 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
29 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
30 #include "gc_implementation/shared/gcTrace.hpp"
31 #include "gc_implementation/shared/mutableSpace.hpp"
32 #include "memory/allocation.inline.hpp"
33 #include "memory/memRegion.hpp"
34 #include "memory/padded.inline.hpp"
35 #include "oops/instanceKlass.inline.hpp"
36 #include "oops/instanceMirrorKlass.inline.hpp"
37 #include "oops/objArrayKlass.inline.hpp"
38 #include "oops/oop.inline.hpp"
39 #include "utilities/stack.inline.hpp"
40
41 PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL;
42 OopStarTaskQueueSet* PSPromotionManager::_stack_array_depth = NULL;
43 PSOldGen* PSPromotionManager::_old_gen = NULL;
44 MutableSpace* PSPromotionManager::_young_space = NULL;
45
46 void PSPromotionManager::initialize() {
47 ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
48
49 _old_gen = heap->old_gen();
50 _young_space = heap->young_gen()->to_space();
51
52 // To prevent false sharing, we pad the PSPromotionManagers
53 // and make sure that the first instance starts at a cache line.
54 assert(_manager_array == NULL, "Attempt to initialize twice");
55 _manager_array = PaddedArray<PSPromotionManager, mtGC>::create_unfreeable(ParallelGCThreads + 1);
56 guarantee(_manager_array != NULL, "Could not initialize promotion manager");
57
58 _stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads);
59 guarantee(_stack_array_depth != NULL, "Could not initialize promotion manager");
60
61 // Create and register the PSPromotionManager(s) for the worker threads.
62 for(uint i=0; i<ParallelGCThreads; i++) {
63 stack_array_depth()->register_queue(i, _manager_array[i].claimed_stack_depth());
64 }
65 // The VMThread gets its own PSPromotionManager, which is not available
66 // for work stealing.
67 }
70 // psScavenge.inline.hpp and psPromotionManager.inline.hpp.
71 bool PSPromotionManager::should_scavenge(oop* p, bool check_to_space) {
72 return PSScavenge::should_scavenge(p, check_to_space);
73 }
74 bool PSPromotionManager::should_scavenge(narrowOop* p, bool check_to_space) {
75 return PSScavenge::should_scavenge(p, check_to_space);
76 }
77
78 PSPromotionManager* PSPromotionManager::gc_thread_promotion_manager(int index) {
79 assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
80 assert(_manager_array != NULL, "Sanity");
81 return &_manager_array[index];
82 }
83
84 PSPromotionManager* PSPromotionManager::vm_thread_promotion_manager() {
85 assert(_manager_array != NULL, "Sanity");
86 return &_manager_array[ParallelGCThreads];
87 }
88
89 void PSPromotionManager::pre_scavenge() {
90 ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
91
92 _young_space = heap->young_gen()->to_space();
93
94 for(uint i=0; i<ParallelGCThreads+1; i++) {
95 manager_array(i)->reset();
96 }
97 }
98
99 bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) {
100 bool promotion_failure_occurred = false;
101
102 TASKQUEUE_STATS_ONLY(if (PrintTaskqueue) print_taskqueue_stats());
103 for (uint i = 0; i < ParallelGCThreads + 1; i++) {
104 PSPromotionManager* manager = manager_array(i);
105 assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
106 if (manager->_promotion_failed_info.has_failed()) {
107 gc_tracer.report_promotion_failed(manager->_promotion_failed_info);
108 promotion_failure_occurred = true;
109 }
110 manager->flush_labs();
113 }
114
115 #if TASKQUEUE_STATS
116 void
117 PSPromotionManager::print_local_stats(outputStream* const out, uint i) const {
118 #define FMT " " SIZE_FORMAT_W(10)
119 out->print_cr("%3u" FMT FMT FMT FMT, i, _masked_pushes, _masked_steals,
120 _arrays_chunked, _array_chunks_processed);
121 #undef FMT
122 }
123
124 static const char* const pm_stats_hdr[] = {
125 " --------masked------- arrays array",
126 "thr push steal chunked chunks",
127 "--- ---------- ---------- ---------- ----------"
128 };
129
130 void
131 PSPromotionManager::print_taskqueue_stats(outputStream* const out) {
132 out->print_cr("== GC Tasks Stats, GC %3d",
133 ParallelScavengeHeap::heap()->total_collections());
134
135 TaskQueueStats totals;
136 out->print("thr "); TaskQueueStats::print_header(1, out); out->cr();
137 out->print("--- "); TaskQueueStats::print_header(2, out); out->cr();
138 for (uint i = 0; i < ParallelGCThreads + 1; ++i) {
139 TaskQueueStats& next = manager_array(i)->_claimed_stack_depth.stats;
140 out->print("%3d ", i); next.print(out); out->cr();
141 totals += next;
142 }
143 out->print("tot "); totals.print(out); out->cr();
144
145 const uint hlines = sizeof(pm_stats_hdr) / sizeof(pm_stats_hdr[0]);
146 for (uint i = 0; i < hlines; ++i) out->print_cr("%s", pm_stats_hdr[i]);
147 for (uint i = 0; i < ParallelGCThreads + 1; ++i) {
148 manager_array(i)->print_local_stats(out, i);
149 }
150 }
151
152 void
153 PSPromotionManager::reset_stats() {
154 claimed_stack_depth()->stats.reset();
155 _masked_pushes = _masked_steals = 0;
156 _arrays_chunked = _array_chunks_processed = 0;
157 }
158 #endif // TASKQUEUE_STATS
159
160 PSPromotionManager::PSPromotionManager() {
161 ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
162
163 // We set the old lab's start array.
164 _old_lab.set_start_array(old_gen()->start_array());
165
166 uint queue_size;
167 claimed_stack_depth()->initialize();
168 queue_size = claimed_stack_depth()->max_elems();
169
170 _totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0);
171 if (_totally_drain) {
172 _target_stack_size = 0;
173 } else {
174 // don't let the target stack size to be more than 1/4 of the entries
175 _target_stack_size = (uint) MIN2((uint) GCDrainStackTargetSize,
176 (uint) (queue_size / 4));
177 }
178
179 _array_chunk_size = ParGCArrayScanChunk;
180 // let's choose 1.5x the chunk size
181 _min_array_size_for_chunking = 3 * _array_chunk_size / 2;
182
183 reset();
184 }
185
186 void PSPromotionManager::reset() {
187 assert(stacks_empty(), "reset of non-empty stack");
188
189 // We need to get an assert in here to make sure the labs are always flushed.
190
191 ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
192
193 // Do not prefill the LAB's, save heap wastage!
194 HeapWord* lab_base = young_space()->top();
195 _young_lab.initialize(MemRegion(lab_base, (size_t)0));
196 _young_gen_is_full = false;
197
198 lab_base = old_gen()->object_space()->top();
199 _old_lab.initialize(MemRegion(lab_base, (size_t)0));
200 _old_gen_is_full = false;
201
202 _promotion_failed_info.reset();
203
204 TASKQUEUE_STATS_ONLY(reset_stats());
205 }
206
207
208 void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
209 totally_drain = totally_drain || _totally_drain;
210
211 #ifdef ASSERT
212 ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
213 MutableSpace* to_space = heap->young_gen()->to_space();
214 MutableSpace* old_space = heap->old_gen()->object_space();
215 #endif /* ASSERT */
216
217 OopStarTaskQueue* const tq = claimed_stack_depth();
218 do {
219 StarTask p;
220
221 // Drain overflow stack first, so other threads can steal from
222 // claimed stack while we work.
223 while (tq->pop_overflow(p)) {
224 process_popped_location_depth(p);
225 }
226
227 if (totally_drain) {
228 while (tq->pop_local(p)) {
229 process_popped_location_depth(p);
230 }
231 } else {
232 while (tq->size() > _target_stack_size && tq->pop_local(p)) {
|