Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.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 | da91efe96a93 |
children | 63a4eb8bcd23 78bbf4d43a14 |
rev | line source |
---|---|
1521 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6028
diff
changeset
|
2 * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. |
1521 | 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:
1546
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1546
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:
1546
diff
changeset
|
21 * questions. |
1521 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" | |
27 #include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp" | |
28 #include "oops/markOop.inline.hpp" | |
29 #include "oops/oop.inline.hpp" | |
1521 | 30 |
31 ///////////////////////////////////////////////////////////////////////// | |
32 //// PromotionInfo | |
33 ///////////////////////////////////////////////////////////////////////// | |
34 | |
35 | |
36 ////////////////////////////////////////////////////////////////////////////// | |
37 // We go over the list of promoted objects, removing each from the list, | |
38 // and applying the closure (this may, in turn, add more elements to | |
39 // the tail of the promoted list, and these newly added objects will | |
40 // also be processed) until the list is empty. | |
41 // To aid verification and debugging, in the non-product builds | |
42 // we actually forward _promoHead each time we process a promoted oop. | |
43 // Note that this is not necessary in general (i.e. when we don't need to | |
44 // call PromotionInfo::verify()) because oop_iterate can only add to the | |
45 // end of _promoTail, and never needs to look at _promoHead. | |
46 | |
47 #define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix) \ | |
48 \ | |
49 void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) { \ | |
50 NOT_PRODUCT(verify()); \ | |
51 PromotedObject *curObj, *nextObj; \ | |
52 for (curObj = _promoHead; curObj != NULL; curObj = nextObj) { \ | |
53 if ((nextObj = curObj->next()) == NULL) { \ | |
54 /* protect ourselves against additions due to closure application \ | |
55 below by resetting the list. */ \ | |
56 assert(_promoTail == curObj, "Should have been the tail"); \ | |
57 _promoHead = _promoTail = NULL; \ | |
58 } \ | |
59 if (curObj->hasDisplacedMark()) { \ | |
60 /* restore displaced header */ \ | |
61 oop(curObj)->set_mark(nextDisplacedHeader()); \ | |
62 } else { \ | |
63 /* restore prototypical header */ \ | |
64 oop(curObj)->init_mark(); \ | |
65 } \ | |
66 /* The "promoted_mark" should now not be set */ \ | |
67 assert(!curObj->hasPromotedMark(), \ | |
68 "Should have been cleared by restoring displaced mark-word"); \ | |
69 NOT_PRODUCT(_promoHead = nextObj); \ | |
70 if (cl != NULL) oop(curObj)->oop_iterate(cl); \ | |
71 if (nextObj == NULL) { /* start at head of list reset above */ \ | |
72 nextObj = _promoHead; \ | |
73 } \ | |
74 } \ | |
75 assert(noPromotions(), "post-condition violation"); \ | |
76 assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\ | |
77 assert(_spoolHead == _spoolTail, "emptied spooling buffers"); \ | |
78 assert(_firstIndex == _nextIndex, "empty buffer"); \ | |
79 } | |
80 | |
81 // This should have been ALL_SINCE_...() just like the others, | |
82 // but, because the body of the method above is somehwat longer, | |
83 // the MSVC compiler cannot cope; as a workaround, we split the | |
84 // macro into its 3 constituent parts below (see original macro | |
85 // definition in specializedOopClosures.hpp). | |
86 SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN) | |
87 PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v) | |
88 | |
89 | |
90 // Return the next displaced header, incrementing the pointer and | |
91 // recycling spool area as necessary. | |
92 markOop PromotionInfo::nextDisplacedHeader() { | |
93 assert(_spoolHead != NULL, "promotionInfo inconsistency"); | |
94 assert(_spoolHead != _spoolTail || _firstIndex < _nextIndex, | |
95 "Empty spool space: no displaced header can be fetched"); | |
96 assert(_spoolHead->bufferSize > _firstIndex, "Off by one error at head?"); | |
97 markOop hdr = _spoolHead->displacedHdr[_firstIndex]; | |
98 // Spool forward | |
99 if (++_firstIndex == _spoolHead->bufferSize) { // last location in this block | |
100 // forward to next block, recycling this block into spare spool buffer | |
101 SpoolBlock* tmp = _spoolHead->nextSpoolBlock; | |
102 assert(_spoolHead != _spoolTail, "Spooling storage mix-up"); | |
103 _spoolHead->nextSpoolBlock = _spareSpool; | |
104 _spareSpool = _spoolHead; | |
105 _spoolHead = tmp; | |
106 _firstIndex = 1; | |
107 NOT_PRODUCT( | |
108 if (_spoolHead == NULL) { // all buffers fully consumed | |
109 assert(_spoolTail == NULL && _nextIndex == 1, | |
110 "spool buffers processing inconsistency"); | |
111 } | |
112 ) | |
113 } | |
114 return hdr; | |
115 } | |
116 | |
117 void PromotionInfo::track(PromotedObject* trackOop) { | |
118 track(trackOop, oop(trackOop)->klass()); | |
119 } | |
120 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6028
diff
changeset
|
121 void PromotionInfo::track(PromotedObject* trackOop, Klass* klassOfOop) { |
1521 | 122 // make a copy of header as it may need to be spooled |
123 markOop mark = oop(trackOop)->mark(); | |
6028
f69a5d43dc19
7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
jmasa
parents:
1972
diff
changeset
|
124 trackOop->clear_next(); |
1521 | 125 if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) { |
126 // save non-prototypical header, and mark oop | |
127 saveDisplacedHeader(mark); | |
128 trackOop->setDisplacedMark(); | |
129 } else { | |
130 // we'd like to assert something like the following: | |
131 // assert(mark == markOopDesc::prototype(), "consistency check"); | |
132 // ... but the above won't work because the age bits have not (yet) been | |
133 // cleared. The remainder of the check would be identical to the | |
134 // condition checked in must_be_preserved() above, so we don't really | |
135 // have anything useful to check here! | |
136 } | |
137 if (_promoTail != NULL) { | |
138 assert(_promoHead != NULL, "List consistency"); | |
139 _promoTail->setNext(trackOop); | |
140 _promoTail = trackOop; | |
141 } else { | |
142 assert(_promoHead == NULL, "List consistency"); | |
143 _promoHead = _promoTail = trackOop; | |
144 } | |
145 // Mask as newly promoted, so we can skip over such objects | |
146 // when scanning dirty cards | |
147 assert(!trackOop->hasPromotedMark(), "Should not have been marked"); | |
148 trackOop->setPromotedMark(); | |
149 } | |
150 | |
151 // Save the given displaced header, incrementing the pointer and | |
152 // obtaining more spool area as necessary. | |
153 void PromotionInfo::saveDisplacedHeader(markOop hdr) { | |
154 assert(_spoolHead != NULL && _spoolTail != NULL, | |
155 "promotionInfo inconsistency"); | |
156 assert(_spoolTail->bufferSize > _nextIndex, "Off by one error at tail?"); | |
157 _spoolTail->displacedHdr[_nextIndex] = hdr; | |
158 // Spool forward | |
159 if (++_nextIndex == _spoolTail->bufferSize) { // last location in this block | |
160 // get a new spooling block | |
161 assert(_spoolTail->nextSpoolBlock == NULL, "tail should terminate spool list"); | |
162 _splice_point = _spoolTail; // save for splicing | |
163 _spoolTail->nextSpoolBlock = getSpoolBlock(); // might fail | |
164 _spoolTail = _spoolTail->nextSpoolBlock; // might become NULL ... | |
165 // ... but will attempt filling before next promotion attempt | |
166 _nextIndex = 1; | |
167 } | |
168 } | |
169 | |
170 // Ensure that spooling space exists. Return false if spooling space | |
171 // could not be obtained. | |
172 bool PromotionInfo::ensure_spooling_space_work() { | |
173 assert(!has_spooling_space(), "Only call when there is no spooling space"); | |
174 // Try and obtain more spooling space | |
175 SpoolBlock* newSpool = getSpoolBlock(); | |
176 assert(newSpool == NULL || | |
177 (newSpool->bufferSize != 0 && newSpool->nextSpoolBlock == NULL), | |
178 "getSpoolBlock() sanity check"); | |
179 if (newSpool == NULL) { | |
180 return false; | |
181 } | |
182 _nextIndex = 1; | |
183 if (_spoolTail == NULL) { | |
184 _spoolTail = newSpool; | |
185 if (_spoolHead == NULL) { | |
186 _spoolHead = newSpool; | |
187 _firstIndex = 1; | |
188 } else { | |
189 assert(_splice_point != NULL && _splice_point->nextSpoolBlock == NULL, | |
190 "Splice point invariant"); | |
191 // Extra check that _splice_point is connected to list | |
192 #ifdef ASSERT | |
193 { | |
194 SpoolBlock* blk = _spoolHead; | |
195 for (; blk->nextSpoolBlock != NULL; | |
196 blk = blk->nextSpoolBlock); | |
197 assert(blk != NULL && blk == _splice_point, | |
198 "Splice point incorrect"); | |
199 } | |
200 #endif // ASSERT | |
201 _splice_point->nextSpoolBlock = newSpool; | |
202 } | |
203 } else { | |
204 assert(_spoolHead != NULL, "spool list consistency"); | |
205 _spoolTail->nextSpoolBlock = newSpool; | |
206 _spoolTail = newSpool; | |
207 } | |
208 return true; | |
209 } | |
210 | |
211 // Get a free spool buffer from the free pool, getting a new block | |
212 // from the heap if necessary. | |
213 SpoolBlock* PromotionInfo::getSpoolBlock() { | |
214 SpoolBlock* res; | |
215 if ((res = _spareSpool) != NULL) { | |
216 _spareSpool = _spareSpool->nextSpoolBlock; | |
217 res->nextSpoolBlock = NULL; | |
218 } else { // spare spool exhausted, get some from heap | |
219 res = (SpoolBlock*)(space()->allocateScratch(refillSize())); | |
220 if (res != NULL) { | |
221 res->init(); | |
222 } | |
223 } | |
224 assert(res == NULL || res->nextSpoolBlock == NULL, "postcondition"); | |
225 return res; | |
226 } | |
227 | |
228 void PromotionInfo::startTrackingPromotions() { | |
229 assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, | |
230 "spooling inconsistency?"); | |
231 _firstIndex = _nextIndex = 1; | |
232 _tracking = true; | |
233 } | |
234 | |
235 #define CMSPrintPromoBlockInfo 1 | |
236 | |
237 void PromotionInfo::stopTrackingPromotions(uint worker_id) { | |
238 assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, | |
239 "spooling inconsistency?"); | |
240 _firstIndex = _nextIndex = 1; | |
241 _tracking = false; | |
242 if (CMSPrintPromoBlockInfo > 1) { | |
243 print_statistics(worker_id); | |
244 } | |
245 } | |
246 | |
247 void PromotionInfo::print_statistics(uint worker_id) const { | |
248 assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, | |
249 "Else will undercount"); | |
250 assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call"); | |
251 // Count the number of blocks and slots in the free pool | |
252 size_t slots = 0; | |
253 size_t blocks = 0; | |
254 for (SpoolBlock* cur_spool = _spareSpool; | |
255 cur_spool != NULL; | |
256 cur_spool = cur_spool->nextSpoolBlock) { | |
257 // the first entry is just a self-pointer; indices 1 through | |
258 // bufferSize - 1 are occupied (thus, bufferSize - 1 slots). | |
1777
179464550c7d
6983930: CMS: Various small cleanups ca September 2010
ysr
parents:
1716
diff
changeset
|
259 assert((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr, |
179464550c7d
6983930: CMS: Various small cleanups ca September 2010
ysr
parents:
1716
diff
changeset
|
260 "first entry of displacedHdr should be self-referential"); |
1521 | 261 slots += cur_spool->bufferSize - 1; |
262 blocks++; | |
263 } | |
264 if (_spoolHead != NULL) { | |
265 slots += _spoolHead->bufferSize - 1; | |
266 blocks++; | |
267 } | |
268 gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ", | |
269 worker_id, blocks, slots); | |
270 } | |
271 | |
272 // When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex> | |
273 // points to the next slot available for filling. | |
274 // The set of slots holding displaced headers are then all those in the | |
275 // right-open interval denoted by: | |
276 // | |
277 // [ <_spoolHead, _firstIndex>, <_spoolTail, _nextIndex> ) | |
278 // | |
279 // When _spoolTail is NULL, then the set of slots with displaced headers | |
280 // is all those starting at the slot <_spoolHead, _firstIndex> and | |
281 // going up to the last slot of last block in the linked list. | |
282 // In this lartter case, _splice_point points to the tail block of | |
283 // this linked list of blocks holding displaced headers. | |
284 void PromotionInfo::verify() const { | |
285 // Verify the following: | |
286 // 1. the number of displaced headers matches the number of promoted | |
287 // objects that have displaced headers | |
288 // 2. each promoted object lies in this space | |
289 debug_only( | |
290 PromotedObject* junk = NULL; | |
291 assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()), | |
292 "Offset of PromotedObject::_next is expected to align with " | |
293 " the OopDesc::_mark within OopDesc"); | |
294 ) | |
295 // FIXME: guarantee???? | |
296 guarantee(_spoolHead == NULL || _spoolTail != NULL || | |
297 _splice_point != NULL, "list consistency"); | |
298 guarantee(_promoHead == NULL || _promoTail != NULL, "list consistency"); | |
299 // count the number of objects with displaced headers | |
300 size_t numObjsWithDisplacedHdrs = 0; | |
301 for (PromotedObject* curObj = _promoHead; curObj != NULL; curObj = curObj->next()) { | |
302 guarantee(space()->is_in_reserved((HeapWord*)curObj), "Containment"); | |
303 // the last promoted object may fail the mark() != NULL test of is_oop(). | |
304 guarantee(curObj->next() == NULL || oop(curObj)->is_oop(), "must be an oop"); | |
305 if (curObj->hasDisplacedMark()) { | |
306 numObjsWithDisplacedHdrs++; | |
307 } | |
308 } | |
309 // Count the number of displaced headers | |
310 size_t numDisplacedHdrs = 0; | |
311 for (SpoolBlock* curSpool = _spoolHead; | |
312 curSpool != _spoolTail && curSpool != NULL; | |
313 curSpool = curSpool->nextSpoolBlock) { | |
314 // the first entry is just a self-pointer; indices 1 through | |
315 // bufferSize - 1 are occupied (thus, bufferSize - 1 slots). | |
316 guarantee((void*)curSpool->displacedHdr == (void*)&curSpool->displacedHdr, | |
317 "first entry of displacedHdr should be self-referential"); | |
318 numDisplacedHdrs += curSpool->bufferSize - 1; | |
319 } | |
320 guarantee((_spoolHead == _spoolTail) == (numDisplacedHdrs == 0), | |
321 "internal consistency"); | |
322 guarantee(_spoolTail != NULL || _nextIndex == 1, | |
323 "Inconsistency between _spoolTail and _nextIndex"); | |
324 // We overcounted (_firstIndex-1) worth of slots in block | |
325 // _spoolHead and we undercounted (_nextIndex-1) worth of | |
326 // slots in block _spoolTail. We make an appropriate | |
327 // adjustment by subtracting the first and adding the | |
328 // second: - (_firstIndex - 1) + (_nextIndex - 1) | |
329 numDisplacedHdrs += (_nextIndex - _firstIndex); | |
330 guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count"); | |
331 } | |
332 | |
333 void PromotionInfo::print_on(outputStream* st) const { | |
334 SpoolBlock* curSpool = NULL; | |
335 size_t i = 0; | |
1716
be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents:
1552
diff
changeset
|
336 st->print_cr(" start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")", |
1521 | 337 _firstIndex, _nextIndex); |
338 for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL; | |
339 curSpool = curSpool->nextSpoolBlock) { | |
340 curSpool->print_on(st); | |
341 st->print_cr(" active "); | |
342 i++; | |
343 } | |
344 for (curSpool = _spoolTail; curSpool != NULL; | |
345 curSpool = curSpool->nextSpoolBlock) { | |
346 curSpool->print_on(st); | |
347 st->print_cr(" inactive "); | |
348 i++; | |
349 } | |
350 for (curSpool = _spareSpool; curSpool != NULL; | |
351 curSpool = curSpool->nextSpoolBlock) { | |
352 curSpool->print_on(st); | |
353 st->print_cr(" free "); | |
354 i++; | |
355 } | |
1716
be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
ysr
parents:
1552
diff
changeset
|
356 st->print_cr(" " SIZE_FORMAT " header spooling blocks", i); |
1521 | 357 } |
358 | |
359 void SpoolBlock::print_on(outputStream* st) const { | |
360 st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT, | |
361 this, (HeapWord*)displacedHdr + bufferSize, | |
362 bufferSize, nextSpoolBlock); | |
363 } |