1/*
2 * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#ifndef SHARE_GC_SHARED_PLAB_HPP
26#define SHARE_GC_SHARED_PLAB_HPP
27
28#include "gc/shared/gcUtil.hpp"
29#include "memory/allocation.hpp"
30#include "utilities/globalDefinitions.hpp"
31
32// Forward declarations.
33class PLABStats;
34
35// A per-thread allocation buffer used during GC.
36class PLAB: public CHeapObj<mtGC> {
37protected:
38 char head[32];
39 size_t _word_sz; // In HeapWord units
40 HeapWord* _bottom;
41 HeapWord* _top;
42 HeapWord* _end; // Last allocatable address + 1
43 HeapWord* _hard_end; // _end + AlignmentReserve
44 // In support of ergonomic sizing of PLAB's
45 size_t _allocated; // in HeapWord units
46 size_t _wasted; // in HeapWord units
47 size_t _undo_wasted;
48 char tail[32];
49 static size_t AlignmentReserve;
50
51 // Force future allocations to fail and queries for contains()
52 // to return false. Returns the amount of unused space in this PLAB.
53 size_t invalidate() {
54 _end = _hard_end;
55 size_t remaining = pointer_delta(_end, _top); // Calculate remaining space.
56 _top = _end; // Force future allocations to fail.
57 _bottom = _end; // Force future contains() queries to return false.
58 return remaining;
59 }
60
61 // Fill in remaining space with a dummy object and invalidate the PLAB. Returns
62 // the amount of remaining space.
63 size_t retire_internal();
64
65 void add_undo_waste(HeapWord* obj, size_t word_sz);
66
67 // Undo the last allocation in the buffer, which is required to be of the
68 // "obj" of the given "word_sz".
69 void undo_last_allocation(HeapWord* obj, size_t word_sz);
70
71public:
72 // Initializes the buffer to be empty, but with the given "word_sz".
73 // Must get initialized with "set_buf" for an allocation to succeed.
74 PLAB(size_t word_sz);
75
76 static size_t size_required_for_allocation(size_t word_size) { return word_size + AlignmentReserve; }
77
78 // Minimum PLAB size.
79 static size_t min_size();
80 // Maximum PLAB size.
81 static size_t max_size();
82
83 // If an allocation of the given "word_sz" can be satisfied within the
84 // buffer, do the allocation, returning a pointer to the start of the
85 // allocated block. If the allocation request cannot be satisfied,
86 // return NULL.
87 HeapWord* allocate(size_t word_sz) {
88 HeapWord* res = _top;
89 if (pointer_delta(_end, _top) >= word_sz) {
90 _top = _top + word_sz;
91 return res;
92 } else {
93 return NULL;
94 }
95 }
96
97 // Allocate the object aligned to "alignment_in_bytes".
98 inline HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
99
100 // Undo any allocation in the buffer, which is required to be of the
101 // "obj" of the given "word_sz".
102 void undo_allocation(HeapWord* obj, size_t word_sz);
103
104 // The total (word) size of the buffer, including both allocated and
105 // unallocated space.
106 size_t word_sz() { return _word_sz; }
107
108 size_t waste() { return _wasted; }
109 size_t undo_waste() { return _undo_wasted; }
110
111 // The number of words of unallocated space remaining in the buffer.
112 size_t words_remaining() {
113 assert(_end >= _top, "Negative buffer");
114 return pointer_delta(_end, _top, HeapWordSize);
115 }
116
117 bool contains(void* addr) {
118 return (void*)_bottom <= addr && addr < (void*)_hard_end;
119 }
120
121 // Sets the space of the buffer to be [buf, space+word_sz()).
122 void set_buf(HeapWord* buf, size_t new_word_sz) {
123 assert(new_word_sz > AlignmentReserve, "Too small");
124 _word_sz = new_word_sz;
125
126 _bottom = buf;
127 _top = _bottom;
128 _hard_end = _bottom + word_sz();
129 _end = _hard_end - AlignmentReserve;
130 assert(_end >= _top, "Negative buffer");
131 // In support of ergonomic sizing
132 _allocated += word_sz();
133 }
134
135 // Flush allocation statistics into the given PLABStats supporting ergonomic
136 // sizing of PLAB's and retire the current buffer. To be called at the end of
137 // GC.
138 void flush_and_retire_stats(PLABStats* stats);
139
140 // Fills in the unallocated portion of the buffer with a garbage object and updates
141 // statistics. To be called during GC.
142 void retire();
143};
144
145// PLAB book-keeping.
146class PLABStats : public CHeapObj<mtGC> {
147 protected:
148 const char* _description; // Identifying string.
149
150 size_t _allocated; // Total allocated
151 size_t _wasted; // of which wasted (internal fragmentation)
152 size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size)
153 size_t _unused; // Unused in last buffer
154 size_t _desired_net_plab_sz;// Output of filter (below), suitably trimmed and quantized
155 AdaptiveWeightedAverage
156 _filter; // Integrator with decay
157
158 virtual void reset() {
159 _allocated = 0;
160 _wasted = 0;
161 _undo_wasted = 0;
162 _unused = 0;
163 }
164
165 virtual void log_plab_allocation();
166 virtual void log_sizing(size_t calculated, size_t net_desired);
167
168 // helper for adjust_desired_plab_sz().
169 virtual size_t compute_desired_plab_sz();
170
171 public:
172 PLABStats(const char* description, size_t desired_net_plab_sz_, unsigned wt) :
173 _description(description),
174 _allocated(0),
175 _wasted(0),
176 _undo_wasted(0),
177 _unused(0),
178 _desired_net_plab_sz(desired_net_plab_sz_),
179 _filter(wt)
180 { }
181
182 virtual ~PLABStats() { }
183
184 size_t allocated() const { return _allocated; }
185 size_t wasted() const { return _wasted; }
186 size_t unused() const { return _unused; }
187 size_t used() const { return allocated() - (wasted() + unused()); }
188 size_t undo_wasted() const { return _undo_wasted; }
189
190 static const size_t min_size() {
191 return PLAB::min_size();
192 }
193
194 static const size_t max_size() {
195 return PLAB::max_size();
196 }
197
198 // Calculates plab size for current number of gc worker threads.
199 size_t desired_plab_sz(uint no_of_gc_workers);
200
201 // Updates the current desired PLAB size. Computes the new desired PLAB size with one gc worker thread,
202 // updates _desired_plab_sz and clears sensor accumulators.
203 void adjust_desired_plab_sz();
204
205 inline void add_allocated(size_t v);
206
207 inline void add_unused(size_t v);
208
209 inline void add_wasted(size_t v);
210
211 inline void add_undo_wasted(size_t v);
212};
213
214#endif // SHARE_GC_SHARED_PLAB_HPP
215