annotate src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp @ 10374:87c64c0438fb

6976350: G1: deal with fragmentation while copying objects during GC Summary: Create G1ParGCAllocBufferContainer to contain two buffers instead of previously using one buffer, in order to hold the first priority buffer longer. Thus, when some large objects hits the value of free space left in the first priority buffer it has an alternative to fit in the second priority buffer while the first priority buffer is given more chances to try allocating smaller objects. Overall, it will improve heap space efficiency. Reviewed-by: johnc, jmasa, brutisso Contributed-by: tamao <tao.mao@oracle.com>
author tamao
date Mon, 03 Jun 2013 14:37:13 -0700
parents 2e6857353b2c
children 63a4eb8bcd23 cfd4aac53239
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
6595
aaf61e68b255 6818524: G1: use ergonomic resizing of PLABs
johnc
parents: 1972
diff changeset
2 * Copyright (c) 2001, 2012, 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"
6595
aaf61e68b255 6818524: G1: use ergonomic resizing of PLABs
johnc
parents: 1972
diff changeset
26 #include "gc_implementation/shared/parGCAllocBuffer.hpp"
1972
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.
6819
2e6857353b2c 8000311: G1: ParallelGCThreads==0 broken
johnc
parents: 6756
diff changeset
90 void PLABStats::adjust_desired_plab_sz(uint no_of_gc_workers) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
91 assert(ResizePLAB, "Not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
92 if (_allocated == 0) {
6756
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
93 assert(_unused == 0,
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
94 err_msg("Inconsistency in PLAB stats: "
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
95 "_allocated: "SIZE_FORMAT", "
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
96 "_wasted: "SIZE_FORMAT", "
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
97 "_unused: "SIZE_FORMAT", "
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
98 "_used : "SIZE_FORMAT,
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
99 _allocated, _wasted, _unused, _used));
b2ef234911c9 7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents: 6595
diff changeset
100
0
a61af66fc99e Initial load
duke
parents:
diff changeset
101 _allocated = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103 double wasted_frac = (double)_unused/(double)_allocated;
a61af66fc99e Initial load
duke
parents:
diff changeset
104 size_t target_refills = (size_t)((wasted_frac*TargetSurvivorRatio)/
a61af66fc99e Initial load
duke
parents:
diff changeset
105 TargetPLABWastePct);
a61af66fc99e Initial load
duke
parents:
diff changeset
106 if (target_refills == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
107 target_refills = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
109 _used = _allocated - _wasted - _unused;
6819
2e6857353b2c 8000311: G1: ParallelGCThreads==0 broken
johnc
parents: 6756
diff changeset
110 size_t plab_sz = _used/(target_refills*no_of_gc_workers);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
111 if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // Take historical weighted average
a61af66fc99e Initial load
duke
parents:
diff changeset
113 _filter.sample(plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // Clip from above and below, and align to object boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
115 plab_sz = MAX2(min_size(), (size_t)_filter.average());
a61af66fc99e Initial load
duke
parents:
diff changeset
116 plab_sz = MIN2(max_size(), plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
117 plab_sz = align_object_size(plab_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // Latch the result
a61af66fc99e Initial load
duke
parents:
diff changeset
119 if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz);
6595
aaf61e68b255 6818524: G1: use ergonomic resizing of PLABs
johnc
parents: 1972
diff changeset
120 _desired_plab_sz = plab_sz;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // Now clear the accumulators for next round:
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // note this needs to be fixed in the case where we
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // are retaining across scavenges. FIX ME !!! XXX
a61af66fc99e Initial load
duke
parents:
diff changeset
124 _allocated = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
125 _wasted = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
126 _unused = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
130 void ParGCAllocBuffer::print() {
a61af66fc99e Initial load
duke
parents:
diff changeset
131 gclog_or_tty->print("parGCAllocBuffer: _bottom: %p _top: %p _end: %p _hard_end: %p"
a61af66fc99e Initial load
duke
parents:
diff changeset
132 "_retained: %c _retained_filler: [%p,%p)\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
133 _bottom, _top, _end, _hard_end,
a61af66fc99e Initial load
duke
parents:
diff changeset
134 "FT"[_retained], _retained_filler.start(), _retained_filler.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
136 #endif // !PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
137
a61af66fc99e Initial load
duke
parents:
diff changeset
138 const size_t ParGCAllocBufferWithBOT::ChunkSizeInWords =
a61af66fc99e Initial load
duke
parents:
diff changeset
139 MIN2(CardTableModRefBS::par_chunk_heapword_alignment(),
a61af66fc99e Initial load
duke
parents:
diff changeset
140 ((size_t)Generation::GenGrain)/HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
141 const size_t ParGCAllocBufferWithBOT::ChunkSizeInBytes =
a61af66fc99e Initial load
duke
parents:
diff changeset
142 MIN2(CardTableModRefBS::par_chunk_heapword_alignment() * HeapWordSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
143 (size_t)Generation::GenGrain);
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 ParGCAllocBufferWithBOT::ParGCAllocBufferWithBOT(size_t word_sz,
a61af66fc99e Initial load
duke
parents:
diff changeset
146 BlockOffsetSharedArray* bsa) :
a61af66fc99e Initial load
duke
parents:
diff changeset
147 ParGCAllocBuffer(word_sz),
a61af66fc99e Initial load
duke
parents:
diff changeset
148 _bsa(bsa),
a61af66fc99e Initial load
duke
parents:
diff changeset
149 _bt(bsa, MemRegion(_bottom, _hard_end)),
a61af66fc99e Initial load
duke
parents:
diff changeset
150 _true_end(_hard_end)
a61af66fc99e Initial load
duke
parents:
diff changeset
151 {}
a61af66fc99e Initial load
duke
parents:
diff changeset
152
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // The buffer comes with its own BOT, with a shared (obviously) underlying
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // BlockOffsetSharedArray. We manipulate this BOT in the normal way
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // as we would for any contiguous space. However, on accasion we
a61af66fc99e Initial load
duke
parents:
diff changeset
156 // need to do some buffer surgery at the extremities before we
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // start using the body of the buffer for allocations. Such surgery
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // (as explained elsewhere) is to prevent allocation on a card that
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // is in the process of being walked concurrently by another GC thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // When such surgery happens at a point that is far removed (to the
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // right of the current allocation point, top), we use the "contig"
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // parameter below to directly manipulate the shared array without
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // modifying the _next_threshold state in the BOT.
a61af66fc99e Initial load
duke
parents:
diff changeset
164 void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr,
a61af66fc99e Initial load
duke
parents:
diff changeset
165 bool contig) {
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
166 CollectedHeap::fill_with_object(mr);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
167 if (contig) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 _bt.alloc_block(mr.start(), mr.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
169 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 _bt.BlockOffsetArray::alloc_block(mr.start(), mr.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
171 }
a61af66fc99e Initial load
duke
parents:
diff changeset
172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
173
a61af66fc99e Initial load
duke
parents:
diff changeset
174 HeapWord* ParGCAllocBufferWithBOT::allocate_slow(size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 HeapWord* res = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
176 if (_true_end > _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
177 assert((HeapWord*)align_size_down(intptr_t(_hard_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
178 ChunkSizeInBytes) == _hard_end,
a61af66fc99e Initial load
duke
parents:
diff changeset
179 "or else _true_end should be equal to _hard_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
180 assert(_retained, "or else _true_end should be equal to _hard_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
181 assert(_retained_filler.end() <= _top, "INVARIANT");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
182 CollectedHeap::fill_with_object(_retained_filler);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
183 if (_top < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
184 fill_region_with_block(MemRegion(_top, _hard_end), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186 HeapWord* next_hard_end = MIN2(_true_end, _hard_end + ChunkSizeInWords);
a61af66fc99e Initial load
duke
parents:
diff changeset
187 _retained_filler = MemRegion(_hard_end, FillerHeaderSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
188 _bt.alloc_block(_retained_filler.start(), _retained_filler.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
189 _top = _retained_filler.end();
a61af66fc99e Initial load
duke
parents:
diff changeset
190 _hard_end = next_hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
191 _end = _hard_end - AlignmentReserve;
a61af66fc99e Initial load
duke
parents:
diff changeset
192 res = ParGCAllocBuffer::allocate(word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
193 if (res != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
194 _bt.alloc_block(res, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
197 return res;
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
a61af66fc99e Initial load
duke
parents:
diff changeset
201 ParGCAllocBufferWithBOT::undo_allocation(HeapWord* obj, size_t word_sz) {
a61af66fc99e Initial load
duke
parents:
diff changeset
202 ParGCAllocBuffer::undo_allocation(obj, word_sz);
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // This may back us up beyond the previous threshold, so reset.
a61af66fc99e Initial load
duke
parents:
diff changeset
204 _bt.set_region(MemRegion(_top, _hard_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
205 _bt.initialize_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 void ParGCAllocBufferWithBOT::retire(bool end_of_gc, bool retain) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 assert(!retain || end_of_gc, "Can only retain at GC end.");
a61af66fc99e Initial load
duke
parents:
diff changeset
210 if (_retained) {
a61af66fc99e Initial load
duke
parents:
diff changeset
211 // We're about to make the retained_filler into a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
212 _bt.BlockOffsetArray::alloc_block(_retained_filler.start(),
a61af66fc99e Initial load
duke
parents:
diff changeset
213 _retained_filler.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // Reset _hard_end to _true_end (and update _end)
a61af66fc99e Initial load
duke
parents:
diff changeset
216 if (retain && _hard_end != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
217 assert(_hard_end <= _true_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
218 _hard_end = _true_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
219 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
220 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
221 }
a61af66fc99e Initial load
duke
parents:
diff changeset
222 _true_end = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
223 HeapWord* pre_top = _top;
a61af66fc99e Initial load
duke
parents:
diff changeset
224
a61af66fc99e Initial load
duke
parents:
diff changeset
225 ParGCAllocBuffer::retire(end_of_gc, retain);
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // Now any old _retained_filler is cut back to size, the free part is
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // filled with a filler object, and top is past the header of that
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // object.
a61af66fc99e Initial load
duke
parents:
diff changeset
229
a61af66fc99e Initial load
duke
parents:
diff changeset
230 if (retain && _top < _end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
231 assert(end_of_gc && retain, "Or else retain should be false.");
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // If the lab does not start on a card boundary, we don't want to
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // allocate onto that card, since that might lead to concurrent
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // allocation and card scanning, which we don't support. So we fill
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // the first card with a garbage object.
a61af66fc99e Initial load
duke
parents:
diff changeset
236 size_t first_card_index = _bsa->index_for(pre_top);
a61af66fc99e Initial load
duke
parents:
diff changeset
237 HeapWord* first_card_start = _bsa->address_for_index(first_card_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
238 if (first_card_start < pre_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
239 HeapWord* second_card_start =
301
387a62b4be60 6728478: Assertion at parallel promotion from young to old generation
jmasa
parents: 196
diff changeset
240 _bsa->inc_by_region_size(first_card_start);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // Ensure enough room to fill with the smallest block
a61af66fc99e Initial load
duke
parents:
diff changeset
243 second_card_start = MAX2(second_card_start, pre_top + AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // If the end is already in the first card, don't go beyond it!
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // Or if the remainder is too small for a filler object, gobble it up.
a61af66fc99e Initial load
duke
parents:
diff changeset
247 if (_hard_end < second_card_start ||
a61af66fc99e Initial load
duke
parents:
diff changeset
248 pointer_delta(_hard_end, second_card_start) < AlignmentReserve) {
a61af66fc99e Initial load
duke
parents:
diff changeset
249 second_card_start = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251 if (pre_top < second_card_start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
252 MemRegion first_card_suffix(pre_top, second_card_start);
a61af66fc99e Initial load
duke
parents:
diff changeset
253 fill_region_with_block(first_card_suffix, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
255 pre_top = second_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
256 _top = pre_top;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
259
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // If the lab does not end on a card boundary, we don't want to
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // allocate onto that card, since that might lead to concurrent
a61af66fc99e Initial load
duke
parents:
diff changeset
262 // allocation and card scanning, which we don't support. So we fill
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // the last card with a garbage object.
a61af66fc99e Initial load
duke
parents:
diff changeset
264 size_t last_card_index = _bsa->index_for(_hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
265 HeapWord* last_card_start = _bsa->address_for_index(last_card_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
266 if (last_card_start < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // Ensure enough room to fill with the smallest block
a61af66fc99e Initial load
duke
parents:
diff changeset
269 last_card_start = MIN2(last_card_start, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
270
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // If the top is already in the last card, don't go back beyond it!
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // Or if the remainder is too small for a filler object, gobble it up.
a61af66fc99e Initial load
duke
parents:
diff changeset
273 if (_top > last_card_start ||
a61af66fc99e Initial load
duke
parents:
diff changeset
274 pointer_delta(last_card_start, _top) < AlignmentReserve) {
a61af66fc99e Initial load
duke
parents:
diff changeset
275 last_card_start = _top;
a61af66fc99e Initial load
duke
parents:
diff changeset
276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
277 if (last_card_start < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
278 MemRegion last_card_prefix(last_card_start, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
279 fill_region_with_block(last_card_prefix, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
281 _hard_end = last_card_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
282 _end = MAX2(_top, _hard_end - AlignmentReserve);
a61af66fc99e Initial load
duke
parents:
diff changeset
283 _true_end = _hard_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
284 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
286
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // At this point:
a61af66fc99e Initial load
duke
parents:
diff changeset
288 // 1) we had a filler object from the original top to hard_end.
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // 2) We've filled in any partial cards at the front and back.
a61af66fc99e Initial load
duke
parents:
diff changeset
290 if (pre_top < _hard_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
291 // Now we can reset the _bt to do allocation in the given area.
a61af66fc99e Initial load
duke
parents:
diff changeset
292 MemRegion new_filler(pre_top, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
293 fill_region_with_block(new_filler, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
294 _top = pre_top + ParGCAllocBuffer::FillerHeaderSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
295 // If there's no space left, don't retain.
a61af66fc99e Initial load
duke
parents:
diff changeset
296 if (_top >= _end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
297 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
298 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
299 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
301 _retained_filler = MemRegion(pre_top, _top);
a61af66fc99e Initial load
duke
parents:
diff changeset
302 _bt.set_region(MemRegion(_top, _hard_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
303 _bt.initialize_threshold();
a61af66fc99e Initial load
duke
parents:
diff changeset
304 assert(_bt.threshold() > _top, "initialize_threshold failed!");
a61af66fc99e Initial load
duke
parents:
diff changeset
305
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // There may be other reasons for queries into the middle of the
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // filler object. When such queries are done in parallel with
a61af66fc99e Initial load
duke
parents:
diff changeset
308 // allocation, bad things can happen, if the query involves object
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // iteration. So we ensure that such queries do not involve object
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // iteration, by putting another filler object on the boundaries of
a61af66fc99e Initial load
duke
parents:
diff changeset
311 // such queries. One such is the object spanning a parallel card
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // chunk boundary.
a61af66fc99e Initial load
duke
parents:
diff changeset
313
a61af66fc99e Initial load
duke
parents:
diff changeset
314 // "chunk_boundary" is the address of the first chunk boundary less
a61af66fc99e Initial load
duke
parents:
diff changeset
315 // than "hard_end".
a61af66fc99e Initial load
duke
parents:
diff changeset
316 HeapWord* chunk_boundary =
a61af66fc99e Initial load
duke
parents:
diff changeset
317 (HeapWord*)align_size_down(intptr_t(_hard_end-1), ChunkSizeInBytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
318 assert(chunk_boundary < _hard_end, "Or else above did not work.");
a61af66fc99e Initial load
duke
parents:
diff changeset
319 assert(pointer_delta(_true_end, chunk_boundary) >= AlignmentReserve,
a61af66fc99e Initial load
duke
parents:
diff changeset
320 "Consequence of last card handling above.");
a61af66fc99e Initial load
duke
parents:
diff changeset
321
a61af66fc99e Initial load
duke
parents:
diff changeset
322 if (_top <= chunk_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
323 assert(_true_end == _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
324 while (_top <= chunk_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
325 assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve,
a61af66fc99e Initial load
duke
parents:
diff changeset
326 "Consequence of last card handling above.");
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
327 _bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
328 CollectedHeap::fill_with_object(chunk_boundary, _hard_end);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 301
diff changeset
329 _hard_end = chunk_boundary;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
330 chunk_boundary -= ChunkSizeInWords;
a61af66fc99e Initial load
duke
parents:
diff changeset
331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
332 _end = _hard_end - AlignmentReserve;
a61af66fc99e Initial load
duke
parents:
diff changeset
333 assert(_top <= _end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // Now reset the initial filler chunk so it doesn't overlap with
a61af66fc99e Initial load
duke
parents:
diff changeset
335 // the one(s) inserted above.
a61af66fc99e Initial load
duke
parents:
diff changeset
336 MemRegion new_filler(pre_top, _hard_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
337 fill_region_with_block(new_filler, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
339 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
340 _retained = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
341 invalidate();
a61af66fc99e Initial load
duke
parents:
diff changeset
342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
343 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
344 assert(!end_of_gc ||
a61af66fc99e Initial load
duke
parents:
diff changeset
345 (!_retained && _true_end == _hard_end), "Checking.");
a61af66fc99e Initial load
duke
parents:
diff changeset
346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
347 assert(_end <= _hard_end, "Invariant.");
a61af66fc99e Initial load
duke
parents:
diff changeset
348 assert(_top < _end || _top == _hard_end, "Invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
349 }