annotate src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp @ 1951:899bbbdcb6ea

6997298: fatal error: must own lock CMS_markBitMap_lock during heap dump Summary: Since we are at a stop-world pause, the existing CMS-phase checks are sufficient for safety, and the locking check can be safely elided. Elaborated documentation comment to the case where class unloading and verification are disabled, and the query happens when we aren't in the sweeping phase, where the answer "false" would be (almost everywhere) too pessimistic. Reviewed-by: jmasa, johnc, tonyp
author ysr
date Fri, 05 Nov 2010 13:20:37 -0700
parents c18cbe5936b8
children f95d63e2154a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 579
diff changeset
2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
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
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_parGCAllocBuffer.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) :
a61af66fc99e Initial load
duke
parents:
diff changeset
29 _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
30 _end(NULL), _hard_end(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
31 _retained(false), _retained_filler(),
a61af66fc99e Initial load
duke
parents:
diff changeset
32 _allocated(0), _wasted(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
33 {
a61af66fc99e Initial load
duke
parents:
diff changeset
34 assert (min_size() > AlignmentReserve, "Inconsistency!");
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 0
diff changeset
35 // arrayOopDesc::header_size depends on command line initialization.
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 0
diff changeset
36 FillerHeaderSize = align_object_size(arrayOopDesc::header_size(T_INT));
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 0
diff changeset
37 AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
38 }
a61af66fc99e Initial load
duke
parents:
diff changeset
39
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 0
diff changeset
40 size_t ParGCAllocBuffer::FillerHeaderSize;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
41
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // If the minimum object size is greater than MinObjAlignment, we can
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // end up with a shard at the end of the buffer that's smaller than
a61af66fc99e Initial load
duke
parents:
diff changeset
44 // the smallest object. We can't allow that because the buffer must
a61af66fc99e Initial load
duke
parents:
diff changeset
45 // look like it's full of objects when we retire it, so we make
a61af66fc99e Initial load
duke
parents:
diff changeset
46 // sure we have enough space for a filler int array object.
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 0
diff changeset
47 size_t ParGCAllocBuffer::AlignmentReserve;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
48
a61af66fc99e Initial load
duke
parents:
diff changeset
49 void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
50 assert(!retain || end_of_gc, "Can only retain at GC end.");
a61af66fc99e Initial load
duke
parents:
diff changeset
51 if (_retained) {
a61af66fc99e Initial load
duke
parents:
diff changeset
52 // If the buffer had been retained shorten the previous filler object.
a61af66fc99e Initial load
duke
parents:
diff changeset
53 assert(_retained_filler.end() <= _top, "INVARIANT");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
54 CollectedHeap::fill_with_object(_retained_filler);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // Wasted space book-keeping, otherwise (normally) done in invalidate()
a61af66fc99e Initial load
duke
parents:
diff changeset
56 _wasted += _retained_filler.word_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
57 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
58 }
a61af66fc99e Initial load
duke
parents:
diff changeset
59 assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained.");
a61af66fc99e Initial load
duke
parents:
diff changeset
60 if (_top < _hard_end) {
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
61 CollectedHeap::fill_with_object(_top, _hard_end);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
62 if (!retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
64 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
65 // Is there wasted space we'd like to retain for the next GC?
a61af66fc99e Initial load
duke
parents:
diff changeset
66 if (pointer_delta(_end, _top) > FillerHeaderSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
67 _retained = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
68 _retained_filler = MemRegion(_top, FillerHeaderSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
69 _top = _top + FillerHeaderSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
70 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
71 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
72 }
a61af66fc99e Initial load
duke
parents:
diff changeset
73 }
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75 }
a61af66fc99e Initial load
duke
parents:
diff changeset
76
a61af66fc99e Initial load
duke
parents:
diff changeset
77 void ParGCAllocBuffer::flush_stats(PLABStats* stats) {
a61af66fc99e Initial load
duke
parents:
diff changeset
78 assert(ResizePLAB, "Wasted work");
a61af66fc99e Initial load
duke
parents:
diff changeset
79 stats->add_allocated(_allocated);
a61af66fc99e Initial load
duke
parents:
diff changeset
80 stats->add_wasted(_wasted);
a61af66fc99e Initial load
duke
parents:
diff changeset
81 stats->add_unused(pointer_delta(_end, _top));
a61af66fc99e Initial load
duke
parents:
diff changeset
82 }
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // Compute desired plab size and latch result for later
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // use. This should be called once at the end of parallel
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // scavenge; it clears the sensor accumulators.
a61af66fc99e Initial load
duke
parents:
diff changeset
87 void PLABStats::adjust_desired_plab_sz() {
a61af66fc99e Initial load
duke
parents:
diff changeset
88 assert(ResizePLAB, "Not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
89 if (_allocated == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
90 assert(_unused == 0, "Inconsistency in PLAB stats");
a61af66fc99e Initial load
duke
parents:
diff changeset
91 _allocated = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
92 }
a61af66fc99e Initial load
duke
parents:
diff changeset
93 double wasted_frac = (double)_unused/(double)_allocated;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 size_t target_refills = (size_t)((wasted_frac*TargetSurvivorRatio)/
a61af66fc99e Initial load
duke
parents:
diff changeset
95 TargetPLABWastePct);
a61af66fc99e Initial load
duke
parents:
diff changeset
96 if (target_refills == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
97 target_refills = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
98 }
a61af66fc99e Initial load
duke
parents:
diff changeset
99 _used = _allocated - _wasted - _unused;
a61af66fc99e Initial load
duke
parents:
diff changeset
100 size_t plab_sz = _used/(target_refills*ParallelGCThreads);
a61af66fc99e Initial load
duke
parents:
diff changeset
101 if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // Take historical weighted average
a61af66fc99e Initial load
duke
parents:
diff changeset
103 _filter.sample(plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // Clip from above and below, and align to object boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
105 plab_sz = MAX2(min_size(), (size_t)_filter.average());
a61af66fc99e Initial load
duke
parents:
diff changeset
106 plab_sz = MIN2(max_size(), plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
107 plab_sz = align_object_size(plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // Latch the result
a61af66fc99e Initial load
duke
parents:
diff changeset
109 if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
110 if (ResizePLAB) {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 _desired_plab_sz = plab_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // Now clear the accumulators for next round:
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // note this needs to be fixed in the case where we
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // are retaining across scavenges. FIX ME !!! XXX
a61af66fc99e Initial load
duke
parents:
diff changeset
116 _allocated = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 _wasted = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
118 _unused = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
120
a61af66fc99e Initial load
duke
parents:
diff changeset
121 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
122 void ParGCAllocBuffer::print() {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 gclog_or_tty->print("parGCAllocBuffer: _bottom: %p _top: %p _end: %p _hard_end: %p"
a61af66fc99e Initial load
duke
parents:
diff changeset
124 "_retained: %c _retained_filler: [%p,%p)\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
125 _bottom, _top, _end, _hard_end,
a61af66fc99e Initial load
duke
parents:
diff changeset
126 "FT"[_retained], _retained_filler.start(), _retained_filler.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128 #endif // !PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
129
a61af66fc99e Initial load
duke
parents:
diff changeset
130 const size_t ParGCAllocBufferWithBOT::ChunkSizeInWords =
a61af66fc99e Initial load
duke
parents:
diff changeset
131 MIN2(CardTableModRefBS::par_chunk_heapword_alignment(),
a61af66fc99e Initial load
duke
parents:
diff changeset
132 ((size_t)Generation::GenGrain)/HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
133 const size_t ParGCAllocBufferWithBOT::ChunkSizeInBytes =
a61af66fc99e Initial load
duke
parents:
diff changeset
134 MIN2(CardTableModRefBS::par_chunk_heapword_alignment() * HeapWordSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
135 (size_t)Generation::GenGrain);
a61af66fc99e Initial load
duke
parents:
diff changeset
136
a61af66fc99e Initial load
duke
parents:
diff changeset
137 ParGCAllocBufferWithBOT::ParGCAllocBufferWithBOT(size_t word_sz,
a61af66fc99e Initial load
duke
parents:
diff changeset
138 BlockOffsetSharedArray* bsa) :
a61af66fc99e Initial load
duke
parents:
diff changeset
139 ParGCAllocBuffer(word_sz),
a61af66fc99e Initial load
duke
parents:
diff changeset
140 _bsa(bsa),
a61af66fc99e Initial load
duke
parents:
diff changeset
141 _bt(bsa, MemRegion(_bottom, _hard_end)),
a61af66fc99e Initial load
duke
parents:
diff changeset
142 _true_end(_hard_end)
a61af66fc99e Initial load
duke
parents:
diff changeset
143 {}
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // The buffer comes with its own BOT, with a shared (obviously) underlying
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // BlockOffsetSharedArray. We manipulate this BOT in the normal way
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // as we would for any contiguous space. However, on accasion we
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // need to do some buffer surgery at the extremities before we
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // start using the body of the buffer for allocations. Such surgery
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // (as explained elsewhere) is to prevent allocation on a card that
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // is in the process of being walked concurrently by another GC thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
152 // When such surgery happens at a point that is far removed (to the
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // right of the current allocation point, top), we use the "contig"
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // parameter below to directly manipulate the shared array without
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // modifying the _next_threshold state in the BOT.
a61af66fc99e Initial load
duke
parents:
diff changeset
156 void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
157 bool contig) {
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
158 CollectedHeap::fill_with_object(mr);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
159 if (contig) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 _bt.alloc_block(mr.start(), mr.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
161 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
162 _bt.BlockOffsetArray::alloc_block(mr.start(), mr.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 HeapWord* ParGCAllocBufferWithBOT::allocate_slow(size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
167 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
168 if (_true_end > _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 assert((HeapWord*)align_size_down(intptr_t(_hard_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
170 ChunkSizeInBytes) == _hard_end,
a61af66fc99e Initial load
duke
parents:
diff changeset
171 "or else _true_end should be equal to _hard_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
172 assert(_retained, "or else _true_end should be equal to _hard_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
173 assert(_retained_filler.end() <= _top, "INVARIANT");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
174 CollectedHeap::fill_with_object(_retained_filler);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
175 if (_top < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
176 fill_region_with_block(MemRegion(_top, _hard_end), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178 HeapWord* next_hard_end = MIN2(_true_end, _hard_end + ChunkSizeInWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
179 _retained_filler = MemRegion(_hard_end, FillerHeaderSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
180 _bt.alloc_block(_retained_filler.start(), _retained_filler.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
181 _top = _retained_filler.end();
a61af66fc99e Initial load
duke
parents:
diff changeset
182 _hard_end = next_hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 _end = _hard_end - AlignmentReserve;
a61af66fc99e Initial load
duke
parents:
diff changeset
184 res = ParGCAllocBuffer::allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 _bt.alloc_block(res, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192 void
a61af66fc99e Initial load
duke
parents:
diff changeset
193 ParGCAllocBufferWithBOT::undo_allocation(HeapWord* obj, size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
194 ParGCAllocBuffer::undo_allocation(obj, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
195 // This may back us up beyond the previous threshold, so reset.
a61af66fc99e Initial load
duke
parents:
diff changeset
196 _bt.set_region(MemRegion(_top, _hard_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
197 _bt.initialize_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
199
a61af66fc99e Initial load
duke
parents:
diff changeset
200 void ParGCAllocBufferWithBOT::retire(bool end_of_gc, bool retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
201 assert(!retain || end_of_gc, "Can only retain at GC end.");
a61af66fc99e Initial load
duke
parents:
diff changeset
202 if (_retained) {
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // We're about to make the retained_filler into a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
204 _bt.BlockOffsetArray::alloc_block(_retained_filler.start(),
a61af66fc99e Initial load
duke
parents:
diff changeset
205 _retained_filler.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
207 // Reset _hard_end to _true_end (and update _end)
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if (retain && _hard_end != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 assert(_hard_end <= _true_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
210 _hard_end = _true_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
214 _true_end = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
215 HeapWord* pre_top = _top;
a61af66fc99e Initial load
duke
parents:
diff changeset
216
a61af66fc99e Initial load
duke
parents:
diff changeset
217 ParGCAllocBuffer::retire(end_of_gc, retain);
a61af66fc99e Initial load
duke
parents:
diff changeset
218 // Now any old _retained_filler is cut back to size, the free part is
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // filled with a filler object, and top is past the header of that
a61af66fc99e Initial load
duke
parents:
diff changeset
220 // object.
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 if (retain && _top < _end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
223 assert(end_of_gc && retain, "Or else retain should be false.");
a61af66fc99e Initial load
duke
parents:
diff changeset
224 // If the lab does not start on a card boundary, we don't want to
a61af66fc99e Initial load
duke
parents:
diff changeset
225 // allocate onto that card, since that might lead to concurrent
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // allocation and card scanning, which we don't support. So we fill
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // the first card with a garbage object.
a61af66fc99e Initial load
duke
parents:
diff changeset
228 size_t first_card_index = _bsa->index_for(pre_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
229 HeapWord* first_card_start = _bsa->address_for_index(first_card_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
230 if (first_card_start < pre_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
231 HeapWord* second_card_start =
301
387a62b4be60 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 196
diff changeset
232 _bsa->inc_by_region_size(first_card_start);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // Ensure enough room to fill with the smallest block
a61af66fc99e Initial load
duke
parents:
diff changeset
235 second_card_start = MAX2(second_card_start, pre_top + AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // If the end is already in the first card, don't go beyond it!
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // Or if the remainder is too small for a filler object, gobble it up.
a61af66fc99e Initial load
duke
parents:
diff changeset
239 if (_hard_end < second_card_start ||
a61af66fc99e Initial load
duke
parents:
diff changeset
240 pointer_delta(_hard_end, second_card_start) < AlignmentReserve) {
a61af66fc99e Initial load
duke
parents:
diff changeset
241 second_card_start = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
243 if (pre_top < second_card_start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
244 MemRegion first_card_suffix(pre_top, second_card_start);
a61af66fc99e Initial load
duke
parents:
diff changeset
245 fill_region_with_block(first_card_suffix, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
247 pre_top = second_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
248 _top = pre_top;
a61af66fc99e Initial load
duke
parents:
diff changeset
249 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // If the lab does not end on a card boundary, we don't want to
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // allocate onto that card, since that might lead to concurrent
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // allocation and card scanning, which we don't support. So we fill
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // the last card with a garbage object.
a61af66fc99e Initial load
duke
parents:
diff changeset
256 size_t last_card_index = _bsa->index_for(_hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
257 HeapWord* last_card_start = _bsa->address_for_index(last_card_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
258 if (last_card_start < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
259
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // Ensure enough room to fill with the smallest block
a61af66fc99e Initial load
duke
parents:
diff changeset
261 last_card_start = MIN2(last_card_start, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // If the top is already in the last card, don't go back beyond it!
a61af66fc99e Initial load
duke
parents:
diff changeset
264 // Or if the remainder is too small for a filler object, gobble it up.
a61af66fc99e Initial load
duke
parents:
diff changeset
265 if (_top > last_card_start ||
a61af66fc99e Initial load
duke
parents:
diff changeset
266 pointer_delta(last_card_start, _top) < AlignmentReserve) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 last_card_start = _top;
a61af66fc99e Initial load
duke
parents:
diff changeset
268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
269 if (last_card_start < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 MemRegion last_card_prefix(last_card_start, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
271 fill_region_with_block(last_card_prefix, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
273 _hard_end = last_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
274 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
275 _true_end = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
276 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
278
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // At this point:
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // 1) we had a filler object from the original top to hard_end.
a61af66fc99e Initial load
duke
parents:
diff changeset
281 // 2) We've filled in any partial cards at the front and back.
a61af66fc99e Initial load
duke
parents:
diff changeset
282 if (pre_top < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
283 // Now we can reset the _bt to do allocation in the given area.
a61af66fc99e Initial load
duke
parents:
diff changeset
284 MemRegion new_filler(pre_top, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
285 fill_region_with_block(new_filler, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
286 _top = pre_top + ParGCAllocBuffer::FillerHeaderSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // If there's no space left, don't retain.
a61af66fc99e Initial load
duke
parents:
diff changeset
288 if (_top >= _end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
289 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
290 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
291 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
293 _retained_filler = MemRegion(pre_top, _top);
a61af66fc99e Initial load
duke
parents:
diff changeset
294 _bt.set_region(MemRegion(_top, _hard_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
295 _bt.initialize_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
296 assert(_bt.threshold() > _top, "initialize_threshold failed!");
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 // There may be other reasons for queries into the middle of the
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // filler object. When such queries are done in parallel with
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // allocation, bad things can happen, if the query involves object
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // iteration. So we ensure that such queries do not involve object
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // iteration, by putting another filler object on the boundaries of
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // such queries. One such is the object spanning a parallel card
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // chunk boundary.
a61af66fc99e Initial load
duke
parents:
diff changeset
305
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // "chunk_boundary" is the address of the first chunk boundary less
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // than "hard_end".
a61af66fc99e Initial load
duke
parents:
diff changeset
308 HeapWord* chunk_boundary =
a61af66fc99e Initial load
duke
parents:
diff changeset
309 (HeapWord*)align_size_down(intptr_t(_hard_end-1), ChunkSizeInBytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
310 assert(chunk_boundary < _hard_end, "Or else above did not work.");
a61af66fc99e Initial load
duke
parents:
diff changeset
311 assert(pointer_delta(_true_end, chunk_boundary) >= AlignmentReserve,
a61af66fc99e Initial load
duke
parents:
diff changeset
312 "Consequence of last card handling above.");
a61af66fc99e Initial load
duke
parents:
diff changeset
313
a61af66fc99e Initial load
duke
parents:
diff changeset
314 if (_top <= chunk_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
315 assert(_true_end == _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
316 while (_top <= chunk_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
317 assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve,
a61af66fc99e Initial load
duke
parents:
diff changeset
318 "Consequence of last card handling above.");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
319 _bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
320 CollectedHeap::fill_with_object(chunk_boundary, _hard_end);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
321 _hard_end = chunk_boundary;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
322 chunk_boundary -= ChunkSizeInWords;
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
324 _end = _hard_end - AlignmentReserve;
a61af66fc99e Initial load
duke
parents:
diff changeset
325 assert(_top <= _end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
326 // Now reset the initial filler chunk so it doesn't overlap with
a61af66fc99e Initial load
duke
parents:
diff changeset
327 // the one(s) inserted above.
a61af66fc99e Initial load
duke
parents:
diff changeset
328 MemRegion new_filler(pre_top, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
329 fill_region_with_block(new_filler, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
331 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
332 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
333 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
336 assert(!end_of_gc ||
a61af66fc99e Initial load
duke
parents:
diff changeset
337 (!_retained && _true_end == _hard_end), "Checking.");
a61af66fc99e Initial load
duke
parents:
diff changeset
338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
339 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
340 assert(_top < _end || _top == _hard_end, "Invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
341 }