Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp @ 10185:d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
Summary: In graphKit INT operations were generated to access PtrQueue::_index which has type size_t. This is 64 bit on 64-bit machines. No problems occur on little endian machines as long as the index fits into 32 bit, but on big endian machines the upper part is read, which is zero. This leads to unnecessary branches to the slow path in the runtime.
Reviewed-by: twisti, johnc
Contributed-by: Martin Doerr <martin.doerr@sap.com>
author | johnc |
---|---|
date | Wed, 24 Apr 2013 14:48:43 -0700 |
parents | b735136e0d82 |
children | 12f651e29f6b |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4091
diff
changeset
|
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "gc_implementation/parallelScavenge/objectStartArray.hpp" | |
28 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" | |
29 #include "gc_implementation/parallelScavenge/psMarkSweep.hpp" | |
30 #include "gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp" | |
31 #include "gc_implementation/shared/liveRange.hpp" | |
32 #include "gc_implementation/shared/markSweep.inline.hpp" | |
33 #include "gc_implementation/shared/spaceDecorator.hpp" | |
34 #include "oops/oop.inline.hpp" | |
0 | 35 |
36 PSMarkSweepDecorator* PSMarkSweepDecorator::_destination_decorator = NULL; | |
37 | |
38 | |
39 void PSMarkSweepDecorator::set_destination_decorator_tenured() { | |
40 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); | |
41 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); | |
42 | |
43 _destination_decorator = heap->old_gen()->object_mark_sweep(); | |
44 } | |
45 | |
46 void PSMarkSweepDecorator::advance_destination_decorator() { | |
47 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); | |
48 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); | |
49 | |
50 assert(_destination_decorator != NULL, "Sanity"); | |
51 | |
52 PSMarkSweepDecorator* first = heap->old_gen()->object_mark_sweep(); | |
53 PSMarkSweepDecorator* second = heap->young_gen()->eden_mark_sweep(); | |
54 PSMarkSweepDecorator* third = heap->young_gen()->from_mark_sweep(); | |
55 PSMarkSweepDecorator* fourth = heap->young_gen()->to_mark_sweep(); | |
56 | |
57 if ( _destination_decorator == first ) { | |
58 _destination_decorator = second; | |
59 } else if ( _destination_decorator == second ) { | |
60 _destination_decorator = third; | |
61 } else if ( _destination_decorator == third ) { | |
62 _destination_decorator = fourth; | |
63 } else { | |
64 fatal("PSMarkSweep attempting to advance past last compaction area"); | |
65 } | |
66 } | |
67 | |
68 PSMarkSweepDecorator* PSMarkSweepDecorator::destination_decorator() { | |
69 assert(_destination_decorator != NULL, "Sanity"); | |
70 | |
71 return _destination_decorator; | |
72 } | |
73 | |
74 // FIX ME FIX ME FIX ME FIX ME!!!!!!!!! | |
75 // The object forwarding code is duplicated. Factor this out!!!!! | |
76 // | |
77 // This method "precompacts" objects inside its space to dest. It places forwarding | |
78 // pointers into markOops for use by adjust_pointers. If "dest" should overflow, we | |
79 // finish by compacting into our own space. | |
80 | |
81 void PSMarkSweepDecorator::precompact() { | |
82 // Reset our own compact top. | |
83 set_compaction_top(space()->bottom()); | |
84 | |
85 /* We allow some amount of garbage towards the bottom of the space, so | |
86 * we don't start compacting before there is a significant gain to be made. | |
87 * Occasionally, we want to ensure a full compaction, which is determined | |
88 * by the MarkSweepAlwaysCompactCount parameter. This is a significant | |
89 * performance improvement! | |
90 */ | |
4091
d06a2d7fcd5b
7110718: -XX:MarkSweepAlwaysCompactCount=0 crashes the JVM
brutisso
parents:
1972
diff
changeset
|
91 bool skip_dead = (MarkSweepAlwaysCompactCount < 1) |
d06a2d7fcd5b
7110718: -XX:MarkSweepAlwaysCompactCount=0 crashes the JVM
brutisso
parents:
1972
diff
changeset
|
92 || ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0); |
0 | 93 |
438 | 94 size_t allowed_deadspace = 0; |
0 | 95 if (skip_dead) { |
438 | 96 const size_t ratio = allowed_dead_ratio(); |
97 allowed_deadspace = space()->capacity_in_words() * ratio / 100; | |
0 | 98 } |
99 | |
100 // Fetch the current destination decorator | |
101 PSMarkSweepDecorator* dest = destination_decorator(); | |
102 ObjectStartArray* start_array = dest->start_array(); | |
103 | |
104 HeapWord* compact_top = dest->compaction_top(); | |
105 HeapWord* compact_end = dest->space()->end(); | |
106 | |
107 HeapWord* q = space()->bottom(); | |
108 HeapWord* t = space()->top(); | |
109 | |
110 HeapWord* end_of_live= q; /* One byte beyond the last byte of the last | |
111 live object. */ | |
112 HeapWord* first_dead = space()->end(); /* The first dead object. */ | |
113 LiveRange* liveRange = NULL; /* The current live range, recorded in the | |
114 first header of preceding free area. */ | |
115 _first_dead = first_dead; | |
116 | |
117 const intx interval = PrefetchScanIntervalInBytes; | |
118 | |
119 while (q < t) { | |
120 assert(oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() || | |
121 oop(q)->mark()->has_bias_pattern(), | |
122 "these are the only valid states during a mark sweep"); | |
123 if (oop(q)->is_gc_marked()) { | |
124 /* prefetch beyond q */ | |
125 Prefetch::write(q, interval); | |
126 size_t size = oop(q)->size(); | |
127 | |
128 size_t compaction_max_size = pointer_delta(compact_end, compact_top); | |
129 | |
130 // This should only happen if a space in the young gen overflows the | |
131 // old gen. If that should happen, we null out the start_array, because | |
132 // the young spaces are not covered by one. | |
133 while(size > compaction_max_size) { | |
134 // First record the last compact_top | |
135 dest->set_compaction_top(compact_top); | |
136 | |
137 // Advance to the next compaction decorator | |
138 advance_destination_decorator(); | |
139 dest = destination_decorator(); | |
140 | |
141 // Update compaction info | |
142 start_array = dest->start_array(); | |
143 compact_top = dest->compaction_top(); | |
144 compact_end = dest->space()->end(); | |
145 assert(compact_top == dest->space()->bottom(), "Advanced to space already in use"); | |
146 assert(compact_end > compact_top, "Must always be space remaining"); | |
147 compaction_max_size = | |
148 pointer_delta(compact_end, compact_top); | |
149 } | |
150 | |
151 // store the forwarding pointer into the mark word | |
152 if (q != compact_top) { | |
153 oop(q)->forward_to(oop(compact_top)); | |
154 assert(oop(q)->is_gc_marked(), "encoding the pointer should preserve the mark"); | |
155 } else { | |
374
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
156 // if the object isn't moving we can just set the mark to the default |
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
157 // mark and handle it specially later on. |
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
158 oop(q)->init_mark(); |
0 | 159 assert(oop(q)->forwardee() == NULL, "should be forwarded to NULL"); |
160 } | |
161 | |
162 // Update object start array | |
374
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
163 if (start_array) { |
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
164 start_array->allocate_block(compact_top); |
0 | 165 } |
166 | |
167 compact_top += size; | |
168 assert(compact_top <= dest->space()->end(), | |
169 "Exceeding space in destination"); | |
170 | |
171 q += size; | |
172 end_of_live = q; | |
173 } else { | |
174 /* run over all the contiguous dead objects */ | |
175 HeapWord* end = q; | |
176 do { | |
177 /* prefetch beyond end */ | |
178 Prefetch::write(end, interval); | |
179 end += oop(end)->size(); | |
180 } while (end < t && (!oop(end)->is_gc_marked())); | |
181 | |
182 /* see if we might want to pretend this object is alive so that | |
183 * we don't have to compact quite as often. | |
184 */ | |
185 if (allowed_deadspace > 0 && q == compact_top) { | |
186 size_t sz = pointer_delta(end, q); | |
187 if (insert_deadspace(allowed_deadspace, q, sz)) { | |
188 size_t compaction_max_size = pointer_delta(compact_end, compact_top); | |
189 | |
190 // This should only happen if a space in the young gen overflows the | |
191 // old gen. If that should happen, we null out the start_array, because | |
192 // the young spaces are not covered by one. | |
193 while (sz > compaction_max_size) { | |
194 // First record the last compact_top | |
195 dest->set_compaction_top(compact_top); | |
196 | |
197 // Advance to the next compaction decorator | |
198 advance_destination_decorator(); | |
199 dest = destination_decorator(); | |
200 | |
201 // Update compaction info | |
202 start_array = dest->start_array(); | |
203 compact_top = dest->compaction_top(); | |
204 compact_end = dest->space()->end(); | |
205 assert(compact_top == dest->space()->bottom(), "Advanced to space already in use"); | |
206 assert(compact_end > compact_top, "Must always be space remaining"); | |
207 compaction_max_size = | |
208 pointer_delta(compact_end, compact_top); | |
209 } | |
210 | |
211 // store the forwarding pointer into the mark word | |
212 if (q != compact_top) { | |
213 oop(q)->forward_to(oop(compact_top)); | |
214 assert(oop(q)->is_gc_marked(), "encoding the pointer should preserve the mark"); | |
215 } else { | |
216 // if the object isn't moving we can just set the mark to the default | |
374
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
217 // mark and handle it specially later on. |
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
218 oop(q)->init_mark(); |
0 | 219 assert(oop(q)->forwardee() == NULL, "should be forwarded to NULL"); |
220 } | |
221 | |
374
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
222 // Update object start array |
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
223 if (start_array) { |
a4b729f5b611
6716466: par compact - remove VerifyParallelOldWithMarkSweep code
jcoomes
parents:
269
diff
changeset
|
224 start_array->allocate_block(compact_top); |
0 | 225 } |
226 | |
227 compact_top += sz; | |
228 assert(compact_top <= dest->space()->end(), | |
229 "Exceeding space in destination"); | |
230 | |
231 q = end; | |
232 end_of_live = end; | |
233 continue; | |
234 } | |
235 } | |
236 | |
237 /* for the previous LiveRange, record the end of the live objects. */ | |
238 if (liveRange) { | |
239 liveRange->set_end(q); | |
240 } | |
241 | |
242 /* record the current LiveRange object. | |
243 * liveRange->start() is overlaid on the mark word. | |
244 */ | |
245 liveRange = (LiveRange*)q; | |
246 liveRange->set_start(end); | |
247 liveRange->set_end(end); | |
248 | |
249 /* see if this is the first dead region. */ | |
250 if (q < first_dead) { | |
251 first_dead = q; | |
252 } | |
253 | |
254 /* move on to the next object */ | |
255 q = end; | |
256 } | |
257 } | |
258 | |
259 assert(q == t, "just checking"); | |
260 if (liveRange != NULL) { | |
261 liveRange->set_end(q); | |
262 } | |
263 _end_of_live = end_of_live; | |
264 if (end_of_live < first_dead) { | |
265 first_dead = end_of_live; | |
266 } | |
267 _first_dead = first_dead; | |
268 | |
269 // Update compaction top | |
270 dest->set_compaction_top(compact_top); | |
271 } | |
272 | |
438 | 273 bool PSMarkSweepDecorator::insert_deadspace(size_t& allowed_deadspace_words, |
274 HeapWord* q, size_t deadlength) { | |
275 if (allowed_deadspace_words >= deadlength) { | |
276 allowed_deadspace_words -= deadlength; | |
481
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
438
diff
changeset
|
277 CollectedHeap::fill_with_object(q, deadlength); |
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
438
diff
changeset
|
278 oop(q)->set_mark(oop(q)->mark()->set_marked()); |
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
438
diff
changeset
|
279 assert((int) deadlength == oop(q)->size(), "bad filler object size"); |
0 | 280 // Recall that we required "q == compaction_top". |
281 return true; | |
282 } else { | |
283 allowed_deadspace_words = 0; | |
284 return false; | |
285 } | |
286 } | |
287 | |
288 void PSMarkSweepDecorator::adjust_pointers() { | |
289 // adjust all the interior pointers to point at the new locations of objects | |
290 // Used by MarkSweep::mark_sweep_phase3() | |
291 | |
292 HeapWord* q = space()->bottom(); | |
293 HeapWord* t = _end_of_live; // Established by "prepare_for_compaction". | |
294 | |
295 assert(_first_dead <= _end_of_live, "Stands to reason, no?"); | |
296 | |
297 if (q < t && _first_dead > q && | |
298 !oop(q)->is_gc_marked()) { | |
299 // we have a chunk of the space which hasn't moved and we've | |
300 // reinitialized the mark word during the previous pass, so we can't | |
301 // use is_gc_marked for the traversal. | |
302 HeapWord* end = _first_dead; | |
303 | |
304 while (q < end) { | |
305 // point all the oops to the new location | |
306 size_t size = oop(q)->adjust_pointers(); | |
307 q += size; | |
308 } | |
309 | |
310 if (_first_dead == t) { | |
311 q = t; | |
312 } else { | |
313 // $$$ This is funky. Using this to read the previously written | |
314 // LiveRange. See also use below. | |
315 q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); | |
316 } | |
317 } | |
318 const intx interval = PrefetchScanIntervalInBytes; | |
319 | |
320 debug_only(HeapWord* prev_q = NULL); | |
321 while (q < t) { | |
322 // prefetch beyond q | |
323 Prefetch::write(q, interval); | |
324 if (oop(q)->is_gc_marked()) { | |
325 // q is alive | |
326 // point all the oops to the new location | |
327 size_t size = oop(q)->adjust_pointers(); | |
328 debug_only(prev_q = q); | |
329 q += size; | |
330 } else { | |
331 // q is not a live object, so its mark should point at the next | |
332 // live object | |
333 debug_only(prev_q = q); | |
334 q = (HeapWord*) oop(q)->mark()->decode_pointer(); | |
335 assert(q > prev_q, "we should be moving forward through memory"); | |
336 } | |
337 } | |
338 | |
339 assert(q == t, "just checking"); | |
340 } | |
341 | |
342 void PSMarkSweepDecorator::compact(bool mangle_free_space ) { | |
343 // Copy all live objects to their new location | |
344 // Used by MarkSweep::mark_sweep_phase4() | |
345 | |
346 HeapWord* q = space()->bottom(); | |
347 HeapWord* const t = _end_of_live; | |
348 debug_only(HeapWord* prev_q = NULL); | |
349 | |
350 if (q < t && _first_dead > q && | |
351 !oop(q)->is_gc_marked()) { | |
352 #ifdef ASSERT | |
353 // we have a chunk of the space which hasn't moved and we've reinitialized the | |
354 // mark word during the previous pass, so we can't use is_gc_marked for the | |
355 // traversal. | |
356 HeapWord* const end = _first_dead; | |
357 | |
358 while (q < end) { | |
359 size_t size = oop(q)->size(); | |
360 assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); | |
361 debug_only(prev_q = q); | |
362 q += size; | |
363 } | |
364 #endif | |
365 | |
366 if (_first_dead == t) { | |
367 q = t; | |
368 } else { | |
369 // $$$ Funky | |
370 q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer(); | |
371 } | |
372 } | |
373 | |
374 const intx scan_interval = PrefetchScanIntervalInBytes; | |
375 const intx copy_interval = PrefetchCopyIntervalInBytes; | |
376 | |
377 while (q < t) { | |
378 if (!oop(q)->is_gc_marked()) { | |
379 // mark is pointer to next marked oop | |
380 debug_only(prev_q = q); | |
381 q = (HeapWord*) oop(q)->mark()->decode_pointer(); | |
382 assert(q > prev_q, "we should be moving forward through memory"); | |
383 } else { | |
384 // prefetch beyond q | |
385 Prefetch::read(q, scan_interval); | |
386 | |
387 // size and destination | |
388 size_t size = oop(q)->size(); | |
389 HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); | |
390 | |
391 // prefetch beyond compaction_top | |
392 Prefetch::write(compaction_top, copy_interval); | |
393 | |
394 // copy object and reinit its mark | |
395 assert(q != compaction_top, "everything in this pass should be moving"); | |
396 Copy::aligned_conjoint_words(q, compaction_top, size); | |
397 oop(compaction_top)->init_mark(); | |
398 assert(oop(compaction_top)->klass() != NULL, "should have a class"); | |
399 | |
400 debug_only(prev_q = q); | |
401 q += size; | |
402 } | |
403 } | |
404 | |
405 assert(compaction_top() >= space()->bottom() && compaction_top() <= space()->end(), | |
406 "should point inside space"); | |
407 space()->set_top(compaction_top()); | |
408 | |
263
12eea04c8b06
6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents:
113
diff
changeset
|
409 if (mangle_free_space) { |
12eea04c8b06
6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents:
113
diff
changeset
|
410 space()->mangle_unused_area(); |
12eea04c8b06
6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents:
113
diff
changeset
|
411 } |
0 | 412 } |