annotate src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp @ 4155:394404b2d9bd

Removed strict requirement for GRAAL environment variable. It only needs to be set now if the graal directory is not in the directory hierarchy of GraalVM JDK.
author Doug Simon <doug.simon@oracle.com>
date Wed, 21 Dec 2011 11:25:27 +0100
parents f95d63e2154a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
2 * Copyright (c) 2001, 2010, 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
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
26 #include "gc_implementation/parNew/parGCAllocBuffer.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
27 #include "memory/sharedHeap.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
28 #include "oops/arrayOop.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
29 #include "oops/oop.inline.hpp"
0
a61af66fc99e Initial load
duke
parents:
diff changeset
30
a61af66fc99e Initial load
duke
parents:
diff changeset
31 ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) :
a61af66fc99e Initial load
duke
parents:
diff changeset
32 _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
33 _end(NULL), _hard_end(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
34 _retained(false), _retained_filler(),
a61af66fc99e Initial load
duke
parents:
diff changeset
35 _allocated(0), _wasted(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
36 {
a61af66fc99e Initial load
duke
parents:
diff changeset
37 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
38 // 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
39 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
40 AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
41 }
a61af66fc99e Initial load
duke
parents:
diff changeset
42
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 0
diff changeset
43 size_t ParGCAllocBuffer::FillerHeaderSize;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
44
a61af66fc99e Initial load
duke
parents:
diff changeset
45 // If the minimum object size is greater than MinObjAlignment, we can
a61af66fc99e Initial load
duke
parents:
diff changeset
46 // end up with a shard at the end of the buffer that's smaller than
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // the smallest object. We can't allow that because the buffer must
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // look like it's full of objects when we retire it, so we make
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // 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
50 size_t ParGCAllocBuffer::AlignmentReserve;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
53 assert(!retain || end_of_gc, "Can only retain at GC end.");
a61af66fc99e Initial load
duke
parents:
diff changeset
54 if (_retained) {
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // If the buffer had been retained shorten the previous filler object.
a61af66fc99e Initial load
duke
parents:
diff changeset
56 assert(_retained_filler.end() <= _top, "INVARIANT");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
57 CollectedHeap::fill_with_object(_retained_filler);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // Wasted space book-keeping, otherwise (normally) done in invalidate()
a61af66fc99e Initial load
duke
parents:
diff changeset
59 _wasted += _retained_filler.word_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
60 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 }
a61af66fc99e Initial load
duke
parents:
diff changeset
62 assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained.");
a61af66fc99e Initial load
duke
parents:
diff changeset
63 if (_top < _hard_end) {
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
64 CollectedHeap::fill_with_object(_top, _hard_end);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
65 if (!retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
67 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
68 // Is there wasted space we'd like to retain for the next GC?
a61af66fc99e Initial load
duke
parents:
diff changeset
69 if (pointer_delta(_end, _top) > FillerHeaderSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 _retained = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
71 _retained_filler = MemRegion(_top, FillerHeaderSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
72 _top = _top + FillerHeaderSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
73 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
74 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
75 }
a61af66fc99e Initial load
duke
parents:
diff changeset
76 }
a61af66fc99e Initial load
duke
parents:
diff changeset
77 }
a61af66fc99e Initial load
duke
parents:
diff changeset
78 }
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 void ParGCAllocBuffer::flush_stats(PLABStats* stats) {
a61af66fc99e Initial load
duke
parents:
diff changeset
81 assert(ResizePLAB, "Wasted work");
a61af66fc99e Initial load
duke
parents:
diff changeset
82 stats->add_allocated(_allocated);
a61af66fc99e Initial load
duke
parents:
diff changeset
83 stats->add_wasted(_wasted);
a61af66fc99e Initial load
duke
parents:
diff changeset
84 stats->add_unused(pointer_delta(_end, _top));
a61af66fc99e Initial load
duke
parents:
diff changeset
85 }
a61af66fc99e Initial load
duke
parents:
diff changeset
86
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // Compute desired plab size and latch result for later
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // use. This should be called once at the end of parallel
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // scavenge; it clears the sensor accumulators.
a61af66fc99e Initial load
duke
parents:
diff changeset
90 void PLABStats::adjust_desired_plab_sz() {
a61af66fc99e Initial load
duke
parents:
diff changeset
91 assert(ResizePLAB, "Not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
92 if (_allocated == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
93 assert(_unused == 0, "Inconsistency in PLAB stats");
a61af66fc99e Initial load
duke
parents:
diff changeset
94 _allocated = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
95 }
a61af66fc99e Initial load
duke
parents:
diff changeset
96 double wasted_frac = (double)_unused/(double)_allocated;
a61af66fc99e Initial load
duke
parents:
diff changeset
97 size_t target_refills = (size_t)((wasted_frac*TargetSurvivorRatio)/
a61af66fc99e Initial load
duke
parents:
diff changeset
98 TargetPLABWastePct);
a61af66fc99e Initial load
duke
parents:
diff changeset
99 if (target_refills == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 target_refills = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
102 _used = _allocated - _wasted - _unused;
a61af66fc99e Initial load
duke
parents:
diff changeset
103 size_t plab_sz = _used/(target_refills*ParallelGCThreads);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 // Take historical weighted average
a61af66fc99e Initial load
duke
parents:
diff changeset
106 _filter.sample(plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // Clip from above and below, and align to object boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
108 plab_sz = MAX2(min_size(), (size_t)_filter.average());
a61af66fc99e Initial load
duke
parents:
diff changeset
109 plab_sz = MIN2(max_size(), plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
110 plab_sz = align_object_size(plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // Latch the result
a61af66fc99e Initial load
duke
parents:
diff changeset
112 if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
113 if (ResizePLAB) {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 _desired_plab_sz = plab_sz;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // Now clear the accumulators for next round:
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // note this needs to be fixed in the case where we
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // are retaining across scavenges. FIX ME !!! XXX
a61af66fc99e Initial load
duke
parents:
diff changeset
119 _allocated = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
120 _wasted = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 _unused = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
125 void ParGCAllocBuffer::print() {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 gclog_or_tty->print("parGCAllocBuffer: _bottom: %p _top: %p _end: %p _hard_end: %p"
a61af66fc99e Initial load
duke
parents:
diff changeset
127 "_retained: %c _retained_filler: [%p,%p)\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
128 _bottom, _top, _end, _hard_end,
a61af66fc99e Initial load
duke
parents:
diff changeset
129 "FT"[_retained], _retained_filler.start(), _retained_filler.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 #endif // !PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
132
a61af66fc99e Initial load
duke
parents:
diff changeset
133 const size_t ParGCAllocBufferWithBOT::ChunkSizeInWords =
a61af66fc99e Initial load
duke
parents:
diff changeset
134 MIN2(CardTableModRefBS::par_chunk_heapword_alignment(),
a61af66fc99e Initial load
duke
parents:
diff changeset
135 ((size_t)Generation::GenGrain)/HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
136 const size_t ParGCAllocBufferWithBOT::ChunkSizeInBytes =
a61af66fc99e Initial load
duke
parents:
diff changeset
137 MIN2(CardTableModRefBS::par_chunk_heapword_alignment() * HeapWordSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
138 (size_t)Generation::GenGrain);
a61af66fc99e Initial load
duke
parents:
diff changeset
139
a61af66fc99e Initial load
duke
parents:
diff changeset
140 ParGCAllocBufferWithBOT::ParGCAllocBufferWithBOT(size_t word_sz,
a61af66fc99e Initial load
duke
parents:
diff changeset
141 BlockOffsetSharedArray* bsa) :
a61af66fc99e Initial load
duke
parents:
diff changeset
142 ParGCAllocBuffer(word_sz),
a61af66fc99e Initial load
duke
parents:
diff changeset
143 _bsa(bsa),
a61af66fc99e Initial load
duke
parents:
diff changeset
144 _bt(bsa, MemRegion(_bottom, _hard_end)),
a61af66fc99e Initial load
duke
parents:
diff changeset
145 _true_end(_hard_end)
a61af66fc99e Initial load
duke
parents:
diff changeset
146 {}
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // The buffer comes with its own BOT, with a shared (obviously) underlying
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // BlockOffsetSharedArray. We manipulate this BOT in the normal way
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // as we would for any contiguous space. However, on accasion we
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // need to do some buffer surgery at the extremities before we
a61af66fc99e Initial load
duke
parents:
diff changeset
152 // start using the body of the buffer for allocations. Such surgery
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // (as explained elsewhere) is to prevent allocation on a card that
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // is in the process of being walked concurrently by another GC thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // When such surgery happens at a point that is far removed (to the
a61af66fc99e Initial load
duke
parents:
diff changeset
156 // right of the current allocation point, top), we use the "contig"
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // parameter below to directly manipulate the shared array without
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // modifying the _next_threshold state in the BOT.
a61af66fc99e Initial load
duke
parents:
diff changeset
159 void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
160 bool contig) {
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
161 CollectedHeap::fill_with_object(mr);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
162 if (contig) {
a61af66fc99e Initial load
duke
parents:
diff changeset
163 _bt.alloc_block(mr.start(), mr.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
164 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
165 _bt.BlockOffsetArray::alloc_block(mr.start(), mr.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 HeapWord* ParGCAllocBufferWithBOT::allocate_slow(size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
171 if (_true_end > _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
172 assert((HeapWord*)align_size_down(intptr_t(_hard_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
173 ChunkSizeInBytes) == _hard_end,
a61af66fc99e Initial load
duke
parents:
diff changeset
174 "or else _true_end should be equal to _hard_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
175 assert(_retained, "or else _true_end should be equal to _hard_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
176 assert(_retained_filler.end() <= _top, "INVARIANT");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
177 CollectedHeap::fill_with_object(_retained_filler);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
178 if (_top < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
179 fill_region_with_block(MemRegion(_top, _hard_end), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
181 HeapWord* next_hard_end = MIN2(_true_end, _hard_end + ChunkSizeInWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
182 _retained_filler = MemRegion(_hard_end, FillerHeaderSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
183 _bt.alloc_block(_retained_filler.start(), _retained_filler.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
184 _top = _retained_filler.end();
a61af66fc99e Initial load
duke
parents:
diff changeset
185 _hard_end = next_hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
186 _end = _hard_end - AlignmentReserve;
a61af66fc99e Initial load
duke
parents:
diff changeset
187 res = ParGCAllocBuffer::allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
188 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
189 _bt.alloc_block(res, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
192 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 void
a61af66fc99e Initial load
duke
parents:
diff changeset
196 ParGCAllocBufferWithBOT::undo_allocation(HeapWord* obj, size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
197 ParGCAllocBuffer::undo_allocation(obj, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // This may back us up beyond the previous threshold, so reset.
a61af66fc99e Initial load
duke
parents:
diff changeset
199 _bt.set_region(MemRegion(_top, _hard_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
200 _bt.initialize_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
202
a61af66fc99e Initial load
duke
parents:
diff changeset
203 void ParGCAllocBufferWithBOT::retire(bool end_of_gc, bool retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 assert(!retain || end_of_gc, "Can only retain at GC end.");
a61af66fc99e Initial load
duke
parents:
diff changeset
205 if (_retained) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // We're about to make the retained_filler into a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
207 _bt.BlockOffsetArray::alloc_block(_retained_filler.start(),
a61af66fc99e Initial load
duke
parents:
diff changeset
208 _retained_filler.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // Reset _hard_end to _true_end (and update _end)
a61af66fc99e Initial load
duke
parents:
diff changeset
211 if (retain && _hard_end != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
212 assert(_hard_end <= _true_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
213 _hard_end = _true_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
215 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
217 _true_end = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 HeapWord* pre_top = _top;
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 ParGCAllocBuffer::retire(end_of_gc, retain);
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // Now any old _retained_filler is cut back to size, the free part is
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // filled with a filler object, and top is past the header of that
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // object.
a61af66fc99e Initial load
duke
parents:
diff changeset
224
a61af66fc99e Initial load
duke
parents:
diff changeset
225 if (retain && _top < _end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
226 assert(end_of_gc && retain, "Or else retain should be false.");
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // If the lab does not start on a card boundary, we don't want to
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // allocate onto that card, since that might lead to concurrent
a61af66fc99e Initial load
duke
parents:
diff changeset
229 // allocation and card scanning, which we don't support. So we fill
a61af66fc99e Initial load
duke
parents:
diff changeset
230 // the first card with a garbage object.
a61af66fc99e Initial load
duke
parents:
diff changeset
231 size_t first_card_index = _bsa->index_for(pre_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
232 HeapWord* first_card_start = _bsa->address_for_index(first_card_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
233 if (first_card_start < pre_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
234 HeapWord* second_card_start =
301
387a62b4be60 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 196
diff changeset
235 _bsa->inc_by_region_size(first_card_start);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // Ensure enough room to fill with the smallest block
a61af66fc99e Initial load
duke
parents:
diff changeset
238 second_card_start = MAX2(second_card_start, pre_top + AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
239
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // If the end is already in the first card, don't go beyond it!
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // Or if the remainder is too small for a filler object, gobble it up.
a61af66fc99e Initial load
duke
parents:
diff changeset
242 if (_hard_end < second_card_start ||
a61af66fc99e Initial load
duke
parents:
diff changeset
243 pointer_delta(_hard_end, second_card_start) < AlignmentReserve) {
a61af66fc99e Initial load
duke
parents:
diff changeset
244 second_card_start = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
245 }
a61af66fc99e Initial load
duke
parents:
diff changeset
246 if (pre_top < second_card_start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
247 MemRegion first_card_suffix(pre_top, second_card_start);
a61af66fc99e Initial load
duke
parents:
diff changeset
248 fill_region_with_block(first_card_suffix, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
250 pre_top = second_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
251 _top = pre_top;
a61af66fc99e Initial load
duke
parents:
diff changeset
252 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
254
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // If the lab does not end on a card boundary, we don't want to
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // allocate onto that card, since that might lead to concurrent
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // allocation and card scanning, which we don't support. So we fill
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // the last card with a garbage object.
a61af66fc99e Initial load
duke
parents:
diff changeset
259 size_t last_card_index = _bsa->index_for(_hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
260 HeapWord* last_card_start = _bsa->address_for_index(last_card_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
261 if (last_card_start < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // Ensure enough room to fill with the smallest block
a61af66fc99e Initial load
duke
parents:
diff changeset
264 last_card_start = MIN2(last_card_start, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
265
a61af66fc99e Initial load
duke
parents:
diff changeset
266 // If the top is already in the last card, don't go back beyond it!
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // Or if the remainder is too small for a filler object, gobble it up.
a61af66fc99e Initial load
duke
parents:
diff changeset
268 if (_top > last_card_start ||
a61af66fc99e Initial load
duke
parents:
diff changeset
269 pointer_delta(last_card_start, _top) < AlignmentReserve) {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 last_card_start = _top;
a61af66fc99e Initial load
duke
parents:
diff changeset
271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
272 if (last_card_start < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
273 MemRegion last_card_prefix(last_card_start, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
274 fill_region_with_block(last_card_prefix, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 _hard_end = last_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
277 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
278 _true_end = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
279 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 // At this point:
a61af66fc99e Initial load
duke
parents:
diff changeset
283 // 1) we had a filler object from the original top to hard_end.
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // 2) We've filled in any partial cards at the front and back.
a61af66fc99e Initial load
duke
parents:
diff changeset
285 if (pre_top < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // Now we can reset the _bt to do allocation in the given area.
a61af66fc99e Initial load
duke
parents:
diff changeset
287 MemRegion new_filler(pre_top, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
288 fill_region_with_block(new_filler, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 _top = pre_top + ParGCAllocBuffer::FillerHeaderSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
290 // If there's no space left, don't retain.
a61af66fc99e Initial load
duke
parents:
diff changeset
291 if (_top >= _end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
292 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
293 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
294 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
296 _retained_filler = MemRegion(pre_top, _top);
a61af66fc99e Initial load
duke
parents:
diff changeset
297 _bt.set_region(MemRegion(_top, _hard_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
298 _bt.initialize_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
299 assert(_bt.threshold() > _top, "initialize_threshold failed!");
a61af66fc99e Initial load
duke
parents:
diff changeset
300
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // There may be other reasons for queries into the middle of the
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // filler object. When such queries are done in parallel with
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // allocation, bad things can happen, if the query involves object
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // iteration. So we ensure that such queries do not involve object
a61af66fc99e Initial load
duke
parents:
diff changeset
305 // iteration, by putting another filler object on the boundaries of
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // such queries. One such is the object spanning a parallel card
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // chunk boundary.
a61af66fc99e Initial load
duke
parents:
diff changeset
308
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // "chunk_boundary" is the address of the first chunk boundary less
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // than "hard_end".
a61af66fc99e Initial load
duke
parents:
diff changeset
311 HeapWord* chunk_boundary =
a61af66fc99e Initial load
duke
parents:
diff changeset
312 (HeapWord*)align_size_down(intptr_t(_hard_end-1), ChunkSizeInBytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
313 assert(chunk_boundary < _hard_end, "Or else above did not work.");
a61af66fc99e Initial load
duke
parents:
diff changeset
314 assert(pointer_delta(_true_end, chunk_boundary) >= AlignmentReserve,
a61af66fc99e Initial load
duke
parents:
diff changeset
315 "Consequence of last card handling above.");
a61af66fc99e Initial load
duke
parents:
diff changeset
316
a61af66fc99e Initial load
duke
parents:
diff changeset
317 if (_top <= chunk_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 assert(_true_end == _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
319 while (_top <= chunk_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
320 assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve,
a61af66fc99e Initial load
duke
parents:
diff changeset
321 "Consequence of last card handling above.");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
322 _bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
323 CollectedHeap::fill_with_object(chunk_boundary, _hard_end);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
324 _hard_end = chunk_boundary;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
325 chunk_boundary -= ChunkSizeInWords;
a61af66fc99e Initial load
duke
parents:
diff changeset
326 }
a61af66fc99e Initial load
duke
parents:
diff changeset
327 _end = _hard_end - AlignmentReserve;
a61af66fc99e Initial load
duke
parents:
diff changeset
328 assert(_top <= _end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
329 // Now reset the initial filler chunk so it doesn't overlap with
a61af66fc99e Initial load
duke
parents:
diff changeset
330 // the one(s) inserted above.
a61af66fc99e Initial load
duke
parents:
diff changeset
331 MemRegion new_filler(pre_top, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
332 fill_region_with_block(new_filler, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
334 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
335 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
336 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
338 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 assert(!end_of_gc ||
a61af66fc99e Initial load
duke
parents:
diff changeset
340 (!_retained && _true_end == _hard_end), "Checking.");
a61af66fc99e Initial load
duke
parents:
diff changeset
341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
342 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
343 assert(_top < _end || _top == _hard_end, "Invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
344 }