Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp @ 1091:6aa7255741f3
6906727: UseCompressedOops: some card-marking fixes related to object arrays
Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17).
Reviewed-by: kvn, coleenp, jmasa
author | ysr |
---|---|
date | Thu, 03 Dec 2009 15:01:57 -0800 |
parents | 89e0543e1737 |
children | 2a1472c30599 |
rev | line source |
---|---|
0 | 1 /* |
948 | 2 * Copyright 2005-2009 Sun Microsystems, Inc. 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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_psCompactionManager.cpp.incl" | |
27 | |
28 PSOldGen* ParCompactionManager::_old_gen = NULL; | |
29 ParCompactionManager** ParCompactionManager::_manager_array = NULL; | |
30 OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; | |
31 ObjectStartArray* ParCompactionManager::_start_array = NULL; | |
32 ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
33 RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; |
0 | 34 |
35 ParCompactionManager::ParCompactionManager() : | |
36 _action(CopyAndUpdate) { | |
37 | |
38 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); | |
39 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); | |
40 | |
41 _old_gen = heap->old_gen(); | |
42 _start_array = old_gen()->start_array(); | |
43 | |
44 | |
45 marking_stack()->initialize(); | |
46 | |
47 // We want the overflow stack to be permanent | |
48 _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true); | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
49 #ifdef USE_RegionTaskQueueWithOverflow |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
50 region_stack()->initialize(); |
0 | 51 #else |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
52 region_stack()->initialize(); |
0 | 53 |
54 // We want the overflow stack to be permanent | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
55 _region_overflow_stack = |
0 | 56 new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true); |
57 #endif | |
58 | |
59 // Note that _revisit_klass_stack is allocated out of the | |
60 // C heap (as opposed to out of ResourceArena). | |
61 int size = | |
62 (SystemDictionary::number_of_classes() * 2) * 2 / ParallelGCThreads; | |
63 _revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(size, true); | |
941 | 64 // From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will |
65 // have to do for now until we are able to investigate a more optimal setting. | |
66 _revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true); | |
0 | 67 |
68 } | |
69 | |
70 ParCompactionManager::~ParCompactionManager() { | |
71 delete _overflow_stack; | |
72 delete _revisit_klass_stack; | |
941 | 73 delete _revisit_mdo_stack; |
0 | 74 // _manager_array and _stack_array are statics |
75 // shared with all instances of ParCompactionManager | |
76 // should not be deallocated. | |
77 } | |
78 | |
79 void ParCompactionManager::initialize(ParMarkBitMap* mbm) { | |
80 assert(PSParallelCompact::gc_task_manager() != NULL, | |
81 "Needed for initialization"); | |
82 | |
83 _mark_bitmap = mbm; | |
84 | |
85 uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers(); | |
86 | |
87 assert(_manager_array == NULL, "Attempt to initialize twice"); | |
88 _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 ); | |
89 guarantee(_manager_array != NULL, "Could not initialize promotion manager"); | |
90 | |
91 _stack_array = new OopTaskQueueSet(parallel_gc_threads); | |
92 guarantee(_stack_array != NULL, "Count not initialize promotion manager"); | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
93 _region_array = new RegionTaskQueueSet(parallel_gc_threads); |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
94 guarantee(_region_array != NULL, "Count not initialize promotion manager"); |
0 | 95 |
96 // Create and register the ParCompactionManager(s) for the worker threads. | |
97 for(uint i=0; i<parallel_gc_threads; i++) { | |
98 _manager_array[i] = new ParCompactionManager(); | |
99 guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager"); | |
100 stack_array()->register_queue(i, _manager_array[i]->marking_stack()); | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
101 #ifdef USE_RegionTaskQueueWithOverflow |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
102 region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue()); |
0 | 103 #else |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
104 region_array()->register_queue(i, _manager_array[i]->region_stack()); |
0 | 105 #endif |
106 } | |
107 | |
108 // The VMThread gets its own ParCompactionManager, which is not available | |
109 // for work stealing. | |
110 _manager_array[parallel_gc_threads] = new ParCompactionManager(); | |
111 guarantee(_manager_array[parallel_gc_threads] != NULL, | |
112 "Could not create ParCompactionManager"); | |
113 assert(PSParallelCompact::gc_task_manager()->workers() != 0, | |
114 "Not initialized?"); | |
115 } | |
116 | |
117 bool ParCompactionManager::should_update() { | |
118 assert(action() != NotValid, "Action is not set"); | |
119 return (action() == ParCompactionManager::Update) || | |
120 (action() == ParCompactionManager::CopyAndUpdate) || | |
121 (action() == ParCompactionManager::UpdateAndCopy); | |
122 } | |
123 | |
124 bool ParCompactionManager::should_copy() { | |
125 assert(action() != NotValid, "Action is not set"); | |
126 return (action() == ParCompactionManager::Copy) || | |
127 (action() == ParCompactionManager::CopyAndUpdate) || | |
128 (action() == ParCompactionManager::UpdateAndCopy); | |
129 } | |
130 | |
131 bool ParCompactionManager::should_verify_only() { | |
132 assert(action() != NotValid, "Action is not set"); | |
133 return action() == ParCompactionManager::VerifyUpdate; | |
134 } | |
135 | |
136 bool ParCompactionManager::should_reset_only() { | |
137 assert(action() != NotValid, "Action is not set"); | |
138 return action() == ParCompactionManager::ResetObjects; | |
139 } | |
140 | |
141 // For now save on a stack | |
142 void ParCompactionManager::save_for_scanning(oop m) { | |
143 stack_push(m); | |
144 } | |
145 | |
146 void ParCompactionManager::stack_push(oop obj) { | |
147 | |
148 if(!marking_stack()->push(obj)) { | |
149 overflow_stack()->push(obj); | |
150 } | |
151 } | |
152 | |
153 oop ParCompactionManager::retrieve_for_scanning() { | |
154 | |
155 // Should not be used in the parallel case | |
156 ShouldNotReachHere(); | |
157 return NULL; | |
158 } | |
159 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
160 // Save region on a stack |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
161 void ParCompactionManager::save_for_processing(size_t region_index) { |
0 | 162 #ifdef ASSERT |
163 const ParallelCompactData& sd = PSParallelCompact::summary_data(); | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
164 ParallelCompactData::RegionData* const region_ptr = sd.region(region_index); |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
165 assert(region_ptr->claimed(), "must be claimed"); |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
166 assert(region_ptr->_pushed++ == 0, "should only be pushed once"); |
0 | 167 #endif |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
168 region_stack_push(region_index); |
0 | 169 } |
170 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
171 void ParCompactionManager::region_stack_push(size_t region_index) { |
0 | 172 |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
173 #ifdef USE_RegionTaskQueueWithOverflow |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
174 region_stack()->save(region_index); |
0 | 175 #else |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
176 if(!region_stack()->push(region_index)) { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
177 region_overflow_stack()->push(region_index); |
0 | 178 } |
179 #endif | |
180 } | |
181 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
182 bool ParCompactionManager::retrieve_for_processing(size_t& region_index) { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
183 #ifdef USE_RegionTaskQueueWithOverflow |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
184 return region_stack()->retrieve(region_index); |
0 | 185 #else |
186 // Should not be used in the parallel case | |
187 ShouldNotReachHere(); | |
188 return false; | |
189 #endif | |
190 } | |
191 | |
192 ParCompactionManager* | |
193 ParCompactionManager::gc_thread_compaction_manager(int index) { | |
194 assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range"); | |
195 assert(_manager_array != NULL, "Sanity"); | |
196 return _manager_array[index]; | |
197 } | |
198 | |
199 void ParCompactionManager::reset() { | |
200 for(uint i=0; i<ParallelGCThreads+1; i++) { | |
201 manager_array(i)->revisit_klass_stack()->clear(); | |
941 | 202 manager_array(i)->revisit_mdo_stack()->clear(); |
0 | 203 } |
204 } | |
205 | |
206 void ParCompactionManager::drain_marking_stacks(OopClosure* blk) { | |
207 #ifdef ASSERT | |
208 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); | |
209 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); | |
210 MutableSpace* to_space = heap->young_gen()->to_space(); | |
211 MutableSpace* old_space = heap->old_gen()->object_space(); | |
212 MutableSpace* perm_space = heap->perm_gen()->object_space(); | |
213 #endif /* ASSERT */ | |
214 | |
215 | |
216 do { | |
217 | |
218 // Drain overflow stack first, so other threads can steal from | |
219 // claimed stack while we work. | |
220 while(!overflow_stack()->is_empty()) { | |
221 oop obj = overflow_stack()->pop(); | |
222 obj->follow_contents(this); | |
223 } | |
224 | |
225 oop obj; | |
226 // obj is a reference!!! | |
227 while (marking_stack()->pop_local(obj)) { | |
228 // It would be nice to assert about the type of objects we might | |
229 // pop, but they can come from anywhere, unfortunately. | |
230 obj->follow_contents(this); | |
231 } | |
232 } while((marking_stack()->size() != 0) || (overflow_stack()->length() != 0)); | |
233 | |
234 assert(marking_stack()->size() == 0, "Sanity"); | |
235 assert(overflow_stack()->length() == 0, "Sanity"); | |
236 } | |
237 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
238 void ParCompactionManager::drain_region_overflow_stack() { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
239 size_t region_index = (size_t) -1; |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
240 while(region_stack()->retrieve_from_overflow(region_index)) { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
241 PSParallelCompact::fill_and_update_region(this, region_index); |
0 | 242 } |
243 } | |
244 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
245 void ParCompactionManager::drain_region_stacks() { |
0 | 246 #ifdef ASSERT |
247 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); | |
248 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); | |
249 MutableSpace* to_space = heap->young_gen()->to_space(); | |
250 MutableSpace* old_space = heap->old_gen()->object_space(); | |
251 MutableSpace* perm_space = heap->perm_gen()->object_space(); | |
252 #endif /* ASSERT */ | |
253 | |
254 #if 1 // def DO_PARALLEL - the serial code hasn't been updated | |
255 do { | |
256 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
257 #ifdef USE_RegionTaskQueueWithOverflow |
0 | 258 // Drain overflow stack first, so other threads can steal from |
259 // claimed stack while we work. | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
260 size_t region_index = (size_t) -1; |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
261 while(region_stack()->retrieve_from_overflow(region_index)) { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
262 PSParallelCompact::fill_and_update_region(this, region_index); |
0 | 263 } |
264 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
265 while (region_stack()->retrieve_from_stealable_queue(region_index)) { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
266 PSParallelCompact::fill_and_update_region(this, region_index); |
0 | 267 } |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
268 } while (!region_stack()->is_empty()); |
0 | 269 #else |
270 // Drain overflow stack first, so other threads can steal from | |
271 // claimed stack while we work. | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
272 while(!region_overflow_stack()->is_empty()) { |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
273 size_t region_index = region_overflow_stack()->pop(); |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
274 PSParallelCompact::fill_and_update_region(this, region_index); |
0 | 275 } |
276 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
277 size_t region_index = -1; |
0 | 278 // obj is a reference!!! |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
279 while (region_stack()->pop_local(region_index)) { |
0 | 280 // It would be nice to assert about the type of objects we might |
281 // pop, but they can come from anywhere, unfortunately. | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
282 PSParallelCompact::fill_and_update_region(this, region_index); |
0 | 283 } |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
284 } while((region_stack()->size() != 0) || |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
285 (region_overflow_stack()->length() != 0)); |
0 | 286 #endif |
287 | |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
288 #ifdef USE_RegionTaskQueueWithOverflow |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
289 assert(region_stack()->is_empty(), "Sanity"); |
0 | 290 #else |
375
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
291 assert(region_stack()->size() == 0, "Sanity"); |
81cd571500b0
6725697: par compact - rename class ChunkData to RegionData
jcoomes
parents:
0
diff
changeset
|
292 assert(region_overflow_stack()->length() == 0, "Sanity"); |
0 | 293 #endif |
294 #else | |
295 oop obj; | |
296 while (obj = retrieve_for_scanning()) { | |
297 obj->follow_contents(this); | |
298 } | |
299 #endif | |
300 } | |
301 | |
302 #ifdef ASSERT | |
303 bool ParCompactionManager::stacks_have_been_allocated() { | |
941 | 304 return (revisit_klass_stack()->data_addr() != NULL && |
305 revisit_mdo_stack()->data_addr() != NULL); | |
0 | 306 } |
307 #endif |