Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp @ 6756:b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
Summary: Reset the fields in ParGCAllocBuffer, that are used for accumulating values for the ResizePLAB sensors in PLABStats, to zero after flushing the values to the PLABStats fields. Flush PLABStats values only when retiring the final allocation buffers prior to disposing of a G1ParScanThreadState object, rather than when retiring every allocation buffer.
Reviewed-by: jwilhelm, jmasa, ysr
author | johnc |
---|---|
date | Thu, 20 Sep 2012 09:52:56 -0700 |
parents | aaf61e68b255 |
children | 2e6857353b2c |
rev | line source |
---|---|
0 | 1 /* |
6595 | 2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
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:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP |
26 #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP | |
27 | |
28 #include "memory/allocation.hpp" | |
1983
c760f78e0a53
7003125: precompiled.hpp is included when precompiled headers are not used
stefank
parents:
1972
diff
changeset
|
29 #include "memory/blockOffsetTable.hpp" |
1972 | 30 #include "memory/threadLocalAllocBuffer.hpp" |
31 #include "utilities/globalDefinitions.hpp" | |
32 | |
0 | 33 // Forward decl. |
34 | |
35 class PLABStats; | |
36 | |
37 // A per-thread allocation buffer used during GC. | |
6197 | 38 class ParGCAllocBuffer: public CHeapObj<mtGC> { |
0 | 39 protected: |
40 char head[32]; | |
41 size_t _word_sz; // in HeapWord units | |
42 HeapWord* _bottom; | |
43 HeapWord* _top; | |
44 HeapWord* _end; // last allocatable address + 1 | |
45 HeapWord* _hard_end; // _end + AlignmentReserve | |
46 bool _retained; // whether we hold a _retained_filler | |
47 MemRegion _retained_filler; | |
48 // In support of ergonomic sizing of PLAB's | |
49 size_t _allocated; // in HeapWord units | |
50 size_t _wasted; // in HeapWord units | |
51 char tail[32]; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
52 static size_t FillerHeaderSize; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
53 static size_t AlignmentReserve; |
0 | 54 |
6756
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
55 // Flush the stats supporting ergonomic sizing of PLAB's |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
56 // Should not be called directly |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
57 void flush_stats(PLABStats* stats); |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
58 |
0 | 59 public: |
60 // Initializes the buffer to be empty, but with the given "word_sz". | |
61 // Must get initialized with "set_buf" for an allocation to succeed. | |
62 ParGCAllocBuffer(size_t word_sz); | |
63 | |
64 static const size_t min_size() { | |
65 return ThreadLocalAllocBuffer::min_size(); | |
66 } | |
67 | |
68 static const size_t max_size() { | |
69 return ThreadLocalAllocBuffer::max_size(); | |
70 } | |
71 | |
72 // If an allocation of the given "word_sz" can be satisfied within the | |
73 // buffer, do the allocation, returning a pointer to the start of the | |
74 // allocated block. If the allocation request cannot be satisfied, | |
75 // return NULL. | |
76 HeapWord* allocate(size_t word_sz) { | |
77 HeapWord* res = _top; | |
634 | 78 if (pointer_delta(_end, _top) >= word_sz) { |
79 _top = _top + word_sz; | |
0 | 80 return res; |
81 } else { | |
82 return NULL; | |
83 } | |
84 } | |
85 | |
86 // Undo the last allocation in the buffer, which is required to be of the | |
87 // "obj" of the given "word_sz". | |
88 void undo_allocation(HeapWord* obj, size_t word_sz) { | |
634 | 89 assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo"); |
90 assert(pointer_delta(_top, obj) == word_sz, "Bad undo"); | |
91 _top = obj; | |
0 | 92 } |
93 | |
94 // The total (word) size of the buffer, including both allocated and | |
95 // unallocted space. | |
96 size_t word_sz() { return _word_sz; } | |
97 | |
98 // Should only be done if we are about to reset with a new buffer of the | |
99 // given size. | |
100 void set_word_size(size_t new_word_sz) { | |
101 assert(new_word_sz > AlignmentReserve, "Too small"); | |
102 _word_sz = new_word_sz; | |
103 } | |
104 | |
105 // The number of words of unallocated space remaining in the buffer. | |
106 size_t words_remaining() { | |
107 assert(_end >= _top, "Negative buffer"); | |
108 return pointer_delta(_end, _top, HeapWordSize); | |
109 } | |
110 | |
111 bool contains(void* addr) { | |
112 return (void*)_bottom <= addr && addr < (void*)_hard_end; | |
113 } | |
114 | |
115 // Sets the space of the buffer to be [buf, space+word_sz()). | |
116 void set_buf(HeapWord* buf) { | |
117 _bottom = buf; | |
118 _top = _bottom; | |
119 _hard_end = _bottom + word_sz(); | |
120 _end = _hard_end - AlignmentReserve; | |
121 assert(_end >= _top, "Negative buffer"); | |
122 // In support of ergonomic sizing | |
123 _allocated += word_sz(); | |
124 } | |
125 | |
126 // Flush the stats supporting ergonomic sizing of PLAB's | |
6756
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
127 // and retire the current buffer. |
6595 | 128 void flush_stats_and_retire(PLABStats* stats, bool end_of_gc, bool retain) { |
0 | 129 // We flush the stats first in order to get a reading of |
130 // unused space in the last buffer. | |
131 if (ResizePLAB) { | |
132 flush_stats(stats); | |
6756
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
133 |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
134 // Since we have flushed the stats we need to clear |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
135 // the _allocated and _wasted fields. Not doing so |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
136 // will artifically inflate the values in the stats |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
137 // to which we add them. |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
138 // The next time we flush these values, we will add |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
139 // what we have just flushed in addition to the size |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
140 // of the buffers allocated between now and then. |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
141 _allocated = 0; |
b2ef234911c9
7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
johnc
parents:
6595
diff
changeset
|
142 _wasted = 0; |
0 | 143 } |
144 // Retire the last allocation buffer. | |
6595 | 145 retire(end_of_gc, retain); |
0 | 146 } |
147 | |
148 // Force future allocations to fail and queries for contains() | |
149 // to return false | |
150 void invalidate() { | |
151 assert(!_retained, "Shouldn't retain an invalidated buffer."); | |
152 _end = _hard_end; | |
153 _wasted += pointer_delta(_end, _top); // unused space | |
154 _top = _end; // force future allocations to fail | |
155 _bottom = _end; // force future contains() queries to return false | |
156 } | |
157 | |
158 // Fills in the unallocated portion of the buffer with a garbage object. | |
159 // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" | |
160 // is true, attempt to re-use the unused portion in the next GC. | |
161 void retire(bool end_of_gc, bool retain); | |
162 | |
163 void print() PRODUCT_RETURN; | |
164 }; | |
165 | |
166 // PLAB stats book-keeping | |
167 class PLABStats VALUE_OBJ_CLASS_SPEC { | |
168 size_t _allocated; // total allocated | |
169 size_t _wasted; // of which wasted (internal fragmentation) | |
170 size_t _unused; // Unused in last buffer | |
171 size_t _used; // derived = allocated - wasted - unused | |
172 size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized | |
173 AdaptiveWeightedAverage | |
174 _filter; // integrator with decay | |
175 | |
176 public: | |
177 PLABStats(size_t desired_plab_sz_, unsigned wt) : | |
178 _allocated(0), | |
179 _wasted(0), | |
180 _unused(0), | |
181 _used(0), | |
182 _desired_plab_sz(desired_plab_sz_), | |
183 _filter(wt) | |
184 { | |
185 size_t min_sz = min_size(); | |
186 size_t max_sz = max_size(); | |
187 size_t aligned_min_sz = align_object_size(min_sz); | |
188 size_t aligned_max_sz = align_object_size(max_sz); | |
189 assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && | |
190 min_sz <= max_sz, | |
191 "PLAB clipping computation in adjust_desired_plab_sz()" | |
192 " may be incorrect"); | |
193 } | |
194 | |
195 static const size_t min_size() { | |
196 return ParGCAllocBuffer::min_size(); | |
197 } | |
198 | |
199 static const size_t max_size() { | |
200 return ParGCAllocBuffer::max_size(); | |
201 } | |
202 | |
203 size_t desired_plab_sz() { | |
204 return _desired_plab_sz; | |
205 } | |
206 | |
207 void adjust_desired_plab_sz(); // filter computation, latches output to | |
208 // _desired_plab_sz, clears sensor accumulators | |
209 | |
210 void add_allocated(size_t v) { | |
211 Atomic::add_ptr(v, &_allocated); | |
212 } | |
213 | |
214 void add_unused(size_t v) { | |
215 Atomic::add_ptr(v, &_unused); | |
216 } | |
217 | |
218 void add_wasted(size_t v) { | |
219 Atomic::add_ptr(v, &_wasted); | |
220 } | |
221 }; | |
222 | |
223 class ParGCAllocBufferWithBOT: public ParGCAllocBuffer { | |
224 BlockOffsetArrayContigSpace _bt; | |
225 BlockOffsetSharedArray* _bsa; | |
226 HeapWord* _true_end; // end of the whole ParGCAllocBuffer | |
227 | |
228 static const size_t ChunkSizeInWords; | |
229 static const size_t ChunkSizeInBytes; | |
230 HeapWord* allocate_slow(size_t word_sz); | |
231 | |
232 void fill_region_with_block(MemRegion mr, bool contig); | |
233 | |
234 public: | |
235 ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa); | |
236 | |
237 HeapWord* allocate(size_t word_sz) { | |
238 HeapWord* res = ParGCAllocBuffer::allocate(word_sz); | |
239 if (res != NULL) { | |
240 _bt.alloc_block(res, word_sz); | |
241 } else { | |
242 res = allocate_slow(word_sz); | |
243 } | |
244 return res; | |
245 } | |
246 | |
247 void undo_allocation(HeapWord* obj, size_t word_sz); | |
248 | |
249 void set_buf(HeapWord* buf_start) { | |
250 ParGCAllocBuffer::set_buf(buf_start); | |
251 _true_end = _hard_end; | |
252 _bt.set_region(MemRegion(buf_start, word_sz())); | |
253 _bt.initialize_threshold(); | |
254 } | |
255 | |
256 void retire(bool end_of_gc, bool retain); | |
257 | |
258 MemRegion range() { | |
259 return MemRegion(_top, _true_end); | |
260 } | |
261 }; | |
1972 | 262 |
263 #endif // SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP |