13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "memory/allocation.hpp"
26 #include "gc/shenandoah/shenandoahForwarding.hpp"
27 #include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp"
28 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
29 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
30 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
31 #include "gc/shenandoah/shenandoahTraversalGC.hpp"
32 #include "gc/shared/space.inline.hpp"
33 #include "memory/iterator.inline.hpp"
34 #include "memory/resourceArea.hpp"
35 #include "memory/universe.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/java.hpp"
38 #include "runtime/mutexLocker.hpp"
39 #include "runtime/os.hpp"
40 #include "runtime/safepoint.hpp"
41
42 size_t ShenandoahHeapRegion::RegionCount = 0;
43 size_t ShenandoahHeapRegion::RegionSizeBytes = 0;
44 size_t ShenandoahHeapRegion::RegionSizeWords = 0;
45 size_t ShenandoahHeapRegion::RegionSizeBytesShift = 0;
46 size_t ShenandoahHeapRegion::RegionSizeWordsShift = 0;
47 size_t ShenandoahHeapRegion::RegionSizeBytesMask = 0;
48 size_t ShenandoahHeapRegion::RegionSizeWordsMask = 0;
49 size_t ShenandoahHeapRegion::HumongousThresholdBytes = 0;
50 size_t ShenandoahHeapRegion::HumongousThresholdWords = 0;
51 size_t ShenandoahHeapRegion::MaxTLABSizeBytes = 0;
52 size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0;
76
77 size_t ShenandoahHeapRegion::region_number() const {
78 return _region_number;
79 }
80
81 void ShenandoahHeapRegion::report_illegal_transition(const char *method) {
82 ResourceMark rm;
83 stringStream ss;
84 ss.print("Illegal region state transition from \"%s\", at %s\n ", region_state_to_string(_state), method);
85 print_on(&ss);
86 fatal("%s", ss.as_string());
87 }
88
89 void ShenandoahHeapRegion::make_regular_allocation() {
90 _heap->assert_heaplock_owned_by_current_thread();
91
92 switch (_state) {
93 case _empty_uncommitted:
94 do_commit();
95 case _empty_committed:
96 _state = _regular;
97 case _regular:
98 case _pinned:
99 return;
100 default:
101 report_illegal_transition("regular allocation");
102 }
103 }
104
105 void ShenandoahHeapRegion::make_regular_bypass() {
106 _heap->assert_heaplock_owned_by_current_thread();
107 assert (_heap->is_full_gc_in_progress() || _heap->is_degenerated_gc_in_progress(),
108 "only for full or degen GC");
109
110 switch (_state) {
111 case _empty_uncommitted:
112 do_commit();
113 case _empty_committed:
114 case _cset:
115 case _humongous_start:
116 case _humongous_cont:
117 _state = _regular;
118 return;
119 case _pinned_cset:
120 _state = _pinned;
121 return;
122 case _regular:
123 case _pinned:
124 return;
125 default:
126 report_illegal_transition("regular bypass");
127 }
128 }
129
130 void ShenandoahHeapRegion::make_humongous_start() {
131 _heap->assert_heaplock_owned_by_current_thread();
132 switch (_state) {
133 case _empty_uncommitted:
134 do_commit();
135 case _empty_committed:
136 _state = _humongous_start;
137 return;
138 default:
139 report_illegal_transition("humongous start allocation");
140 }
141 }
142
143 void ShenandoahHeapRegion::make_humongous_start_bypass() {
144 _heap->assert_heaplock_owned_by_current_thread();
145 assert (_heap->is_full_gc_in_progress(), "only for full GC");
146
147 switch (_state) {
148 case _empty_committed:
149 case _regular:
150 case _humongous_start:
151 case _humongous_cont:
152 _state = _humongous_start;
153 return;
154 default:
155 report_illegal_transition("humongous start bypass");
156 }
157 }
158
159 void ShenandoahHeapRegion::make_humongous_cont() {
160 _heap->assert_heaplock_owned_by_current_thread();
161 switch (_state) {
162 case _empty_uncommitted:
163 do_commit();
164 case _empty_committed:
165 _state = _humongous_cont;
166 return;
167 default:
168 report_illegal_transition("humongous continuation allocation");
169 }
170 }
171
172 void ShenandoahHeapRegion::make_humongous_cont_bypass() {
173 _heap->assert_heaplock_owned_by_current_thread();
174 assert (_heap->is_full_gc_in_progress(), "only for full GC");
175
176 switch (_state) {
177 case _empty_committed:
178 case _regular:
179 case _humongous_start:
180 case _humongous_cont:
181 _state = _humongous_cont;
182 return;
183 default:
184 report_illegal_transition("humongous continuation bypass");
185 }
186 }
187
188 void ShenandoahHeapRegion::make_pinned() {
189 _heap->assert_heaplock_owned_by_current_thread();
190 switch (_state) {
191 case _regular:
192 assert (_critical_pins == 0, "sanity");
193 _state = _pinned;
194 case _pinned_cset:
195 case _pinned:
196 _critical_pins++;
197 return;
198 case _humongous_start:
199 assert (_critical_pins == 0, "sanity");
200 _state = _pinned_humongous_start;
201 case _pinned_humongous_start:
202 _critical_pins++;
203 return;
204 case _cset:
205 guarantee(_heap->cancelled_gc(), "only valid when evac has been cancelled");
206 assert (_critical_pins == 0, "sanity");
207 _state = _pinned_cset;
208 _critical_pins++;
209 return;
210 default:
211 report_illegal_transition("pinning");
212 }
213 }
214
215 void ShenandoahHeapRegion::make_unpinned() {
216 _heap->assert_heaplock_owned_by_current_thread();
217 switch (_state) {
218 case _pinned:
219 assert (_critical_pins > 0, "sanity");
220 _critical_pins--;
221 if (_critical_pins == 0) {
222 _state = _regular;
223 }
224 return;
225 case _regular:
226 case _humongous_start:
227 assert (_critical_pins == 0, "sanity");
228 return;
229 case _pinned_cset:
230 guarantee(_heap->cancelled_gc(), "only valid when evac has been cancelled");
231 assert (_critical_pins > 0, "sanity");
232 _critical_pins--;
233 if (_critical_pins == 0) {
234 _state = _cset;
235 }
236 return;
237 case _pinned_humongous_start:
238 assert (_critical_pins > 0, "sanity");
239 _critical_pins--;
240 if (_critical_pins == 0) {
241 _state = _humongous_start;
242 }
243 return;
244 default:
245 report_illegal_transition("unpinning");
246 }
247 }
248
249 void ShenandoahHeapRegion::make_cset() {
250 _heap->assert_heaplock_owned_by_current_thread();
251 switch (_state) {
252 case _regular:
253 _state = _cset;
254 case _cset:
255 return;
256 default:
257 report_illegal_transition("cset");
258 }
259 }
260
261 void ShenandoahHeapRegion::make_trash() {
262 _heap->assert_heaplock_owned_by_current_thread();
263 switch (_state) {
264 case _cset:
265 // Reclaiming cset regions
266 case _humongous_start:
267 case _humongous_cont:
268 // Reclaiming humongous regions
269 case _regular:
270 // Immediate region reclaim
271 _state = _trash;
272 return;
273 default:
274 report_illegal_transition("trashing");
275 }
276 }
277
278 void ShenandoahHeapRegion::make_trash_immediate() {
279 make_trash();
280
281 // On this path, we know there are no marked objects in the region,
282 // tell marking context about it to bypass bitmap resets.
283 _heap->complete_marking_context()->reset_top_bitmap(this);
284 }
285
286 void ShenandoahHeapRegion::make_empty() {
287 _heap->assert_heaplock_owned_by_current_thread();
288 switch (_state) {
289 case _trash:
290 _state = _empty_committed;
291 _empty_time = os::elapsedTime();
292 return;
293 default:
294 report_illegal_transition("emptying");
295 }
296 }
297
298 void ShenandoahHeapRegion::make_uncommitted() {
299 _heap->assert_heaplock_owned_by_current_thread();
300 switch (_state) {
301 case _empty_committed:
302 do_uncommit();
303 _state = _empty_uncommitted;
304 return;
305 default:
306 report_illegal_transition("uncommiting");
307 }
308 }
309
310 void ShenandoahHeapRegion::make_committed_bypass() {
311 _heap->assert_heaplock_owned_by_current_thread();
312 assert (_heap->is_full_gc_in_progress(), "only for full GC");
313
314 switch (_state) {
315 case _empty_uncommitted:
316 do_commit();
317 _state = _empty_committed;
318 return;
319 default:
320 report_illegal_transition("commit bypass");
321 }
322 }
323
324 void ShenandoahHeapRegion::clear_live_data() {
325 OrderAccess::release_store_fence<size_t>(&_live_data, 0);
326 }
327
328 void ShenandoahHeapRegion::reset_alloc_metadata() {
329 _tlab_allocs = 0;
330 _gclab_allocs = 0;
331 _shared_allocs = 0;
332 _seqnum_first_alloc_mutator = 0;
333 _seqnum_last_alloc_mutator = 0;
334 _seqnum_first_alloc_gc = 0;
335 _seqnum_last_alloc_gc = 0;
336 }
337
661 }
662
663 void ShenandoahHeapRegion::do_commit() {
664 if (!_heap->is_heap_region_special() && !os::commit_memory((char *) _reserved.start(), _reserved.byte_size(), false)) {
665 report_java_out_of_memory("Unable to commit region");
666 }
667 if (!_heap->commit_bitmap_slice(this)) {
668 report_java_out_of_memory("Unable to commit bitmaps for region");
669 }
670 _heap->increase_committed(ShenandoahHeapRegion::region_size_bytes());
671 }
672
673 void ShenandoahHeapRegion::do_uncommit() {
674 if (!_heap->is_heap_region_special() && !os::uncommit_memory((char *) _reserved.start(), _reserved.byte_size())) {
675 report_java_out_of_memory("Unable to uncommit region");
676 }
677 if (!_heap->uncommit_bitmap_slice(this)) {
678 report_java_out_of_memory("Unable to uncommit bitmaps for region");
679 }
680 _heap->decrease_committed(ShenandoahHeapRegion::region_size_bytes());
681 }
|
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "memory/allocation.hpp"
26 #include "gc/shenandoah/shenandoahForwarding.hpp"
27 #include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp"
28 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
29 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
30 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
31 #include "gc/shenandoah/shenandoahTraversalGC.hpp"
32 #include "gc/shared/space.inline.hpp"
33 #include "jfr/jfrEvents.hpp"
34 #include "memory/iterator.inline.hpp"
35 #include "memory/resourceArea.hpp"
36 #include "memory/universe.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "runtime/java.hpp"
39 #include "runtime/mutexLocker.hpp"
40 #include "runtime/os.hpp"
41 #include "runtime/safepoint.hpp"
42
43 size_t ShenandoahHeapRegion::RegionCount = 0;
44 size_t ShenandoahHeapRegion::RegionSizeBytes = 0;
45 size_t ShenandoahHeapRegion::RegionSizeWords = 0;
46 size_t ShenandoahHeapRegion::RegionSizeBytesShift = 0;
47 size_t ShenandoahHeapRegion::RegionSizeWordsShift = 0;
48 size_t ShenandoahHeapRegion::RegionSizeBytesMask = 0;
49 size_t ShenandoahHeapRegion::RegionSizeWordsMask = 0;
50 size_t ShenandoahHeapRegion::HumongousThresholdBytes = 0;
51 size_t ShenandoahHeapRegion::HumongousThresholdWords = 0;
52 size_t ShenandoahHeapRegion::MaxTLABSizeBytes = 0;
53 size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0;
77
78 size_t ShenandoahHeapRegion::region_number() const {
79 return _region_number;
80 }
81
82 void ShenandoahHeapRegion::report_illegal_transition(const char *method) {
83 ResourceMark rm;
84 stringStream ss;
85 ss.print("Illegal region state transition from \"%s\", at %s\n ", region_state_to_string(_state), method);
86 print_on(&ss);
87 fatal("%s", ss.as_string());
88 }
89
90 void ShenandoahHeapRegion::make_regular_allocation() {
91 _heap->assert_heaplock_owned_by_current_thread();
92
93 switch (_state) {
94 case _empty_uncommitted:
95 do_commit();
96 case _empty_committed:
97 set_state(_regular);
98 case _regular:
99 case _pinned:
100 return;
101 default:
102 report_illegal_transition("regular allocation");
103 }
104 }
105
106 void ShenandoahHeapRegion::make_regular_bypass() {
107 _heap->assert_heaplock_owned_by_current_thread();
108 assert (_heap->is_full_gc_in_progress() || _heap->is_degenerated_gc_in_progress(),
109 "only for full or degen GC");
110
111 switch (_state) {
112 case _empty_uncommitted:
113 do_commit();
114 case _empty_committed:
115 case _cset:
116 case _humongous_start:
117 case _humongous_cont:
118 set_state(_regular);
119 return;
120 case _pinned_cset:
121 set_state(_pinned);
122 return;
123 case _regular:
124 case _pinned:
125 return;
126 default:
127 report_illegal_transition("regular bypass");
128 }
129 }
130
131 void ShenandoahHeapRegion::make_humongous_start() {
132 _heap->assert_heaplock_owned_by_current_thread();
133 switch (_state) {
134 case _empty_uncommitted:
135 do_commit();
136 case _empty_committed:
137 set_state(_humongous_start);
138 return;
139 default:
140 report_illegal_transition("humongous start allocation");
141 }
142 }
143
144 void ShenandoahHeapRegion::make_humongous_start_bypass() {
145 _heap->assert_heaplock_owned_by_current_thread();
146 assert (_heap->is_full_gc_in_progress(), "only for full GC");
147
148 switch (_state) {
149 case _empty_committed:
150 case _regular:
151 case _humongous_start:
152 case _humongous_cont:
153 set_state(_humongous_start);
154 return;
155 default:
156 report_illegal_transition("humongous start bypass");
157 }
158 }
159
160 void ShenandoahHeapRegion::make_humongous_cont() {
161 _heap->assert_heaplock_owned_by_current_thread();
162 switch (_state) {
163 case _empty_uncommitted:
164 do_commit();
165 case _empty_committed:
166 set_state(_humongous_cont);
167 return;
168 default:
169 report_illegal_transition("humongous continuation allocation");
170 }
171 }
172
173 void ShenandoahHeapRegion::make_humongous_cont_bypass() {
174 _heap->assert_heaplock_owned_by_current_thread();
175 assert (_heap->is_full_gc_in_progress(), "only for full GC");
176
177 switch (_state) {
178 case _empty_committed:
179 case _regular:
180 case _humongous_start:
181 case _humongous_cont:
182 set_state(_humongous_cont);
183 return;
184 default:
185 report_illegal_transition("humongous continuation bypass");
186 }
187 }
188
189 void ShenandoahHeapRegion::make_pinned() {
190 _heap->assert_heaplock_owned_by_current_thread();
191 switch (_state) {
192 case _regular:
193 assert (_critical_pins == 0, "sanity");
194 set_state(_pinned);
195 case _pinned_cset:
196 case _pinned:
197 _critical_pins++;
198 return;
199 case _humongous_start:
200 assert (_critical_pins == 0, "sanity");
201 set_state(_pinned_humongous_start);
202 case _pinned_humongous_start:
203 _critical_pins++;
204 return;
205 case _cset:
206 guarantee(_heap->cancelled_gc(), "only valid when evac has been cancelled");
207 assert (_critical_pins == 0, "sanity");
208 _state = _pinned_cset;
209 _critical_pins++;
210 return;
211 default:
212 report_illegal_transition("pinning");
213 }
214 }
215
216 void ShenandoahHeapRegion::make_unpinned() {
217 _heap->assert_heaplock_owned_by_current_thread();
218 switch (_state) {
219 case _pinned:
220 assert (_critical_pins > 0, "sanity");
221 _critical_pins--;
222 if (_critical_pins == 0) {
223 set_state(_regular);
224 }
225 return;
226 case _regular:
227 case _humongous_start:
228 assert (_critical_pins == 0, "sanity");
229 return;
230 case _pinned_cset:
231 guarantee(_heap->cancelled_gc(), "only valid when evac has been cancelled");
232 assert (_critical_pins > 0, "sanity");
233 _critical_pins--;
234 if (_critical_pins == 0) {
235 set_state(_cset);
236 }
237 return;
238 case _pinned_humongous_start:
239 assert (_critical_pins > 0, "sanity");
240 _critical_pins--;
241 if (_critical_pins == 0) {
242 set_state(_humongous_start);
243 }
244 return;
245 default:
246 report_illegal_transition("unpinning");
247 }
248 }
249
250 void ShenandoahHeapRegion::make_cset() {
251 _heap->assert_heaplock_owned_by_current_thread();
252 switch (_state) {
253 case _regular:
254 set_state(_cset);
255 case _cset:
256 return;
257 default:
258 report_illegal_transition("cset");
259 }
260 }
261
262 void ShenandoahHeapRegion::make_trash() {
263 _heap->assert_heaplock_owned_by_current_thread();
264 switch (_state) {
265 case _cset:
266 // Reclaiming cset regions
267 case _humongous_start:
268 case _humongous_cont:
269 // Reclaiming humongous regions
270 case _regular:
271 // Immediate region reclaim
272 set_state(_trash);
273 return;
274 default:
275 report_illegal_transition("trashing");
276 }
277 }
278
279 void ShenandoahHeapRegion::make_trash_immediate() {
280 make_trash();
281
282 // On this path, we know there are no marked objects in the region,
283 // tell marking context about it to bypass bitmap resets.
284 _heap->complete_marking_context()->reset_top_bitmap(this);
285 }
286
287 void ShenandoahHeapRegion::make_empty() {
288 _heap->assert_heaplock_owned_by_current_thread();
289 switch (_state) {
290 case _trash:
291 set_state(_empty_committed);
292 _empty_time = os::elapsedTime();
293 return;
294 default:
295 report_illegal_transition("emptying");
296 }
297 }
298
299 void ShenandoahHeapRegion::make_uncommitted() {
300 _heap->assert_heaplock_owned_by_current_thread();
301 switch (_state) {
302 case _empty_committed:
303 do_uncommit();
304 set_state(_empty_uncommitted);
305 return;
306 default:
307 report_illegal_transition("uncommiting");
308 }
309 }
310
311 void ShenandoahHeapRegion::make_committed_bypass() {
312 _heap->assert_heaplock_owned_by_current_thread();
313 assert (_heap->is_full_gc_in_progress(), "only for full GC");
314
315 switch (_state) {
316 case _empty_uncommitted:
317 do_commit();
318 set_state(_empty_committed);
319 return;
320 default:
321 report_illegal_transition("commit bypass");
322 }
323 }
324
325 void ShenandoahHeapRegion::clear_live_data() {
326 OrderAccess::release_store_fence<size_t>(&_live_data, 0);
327 }
328
329 void ShenandoahHeapRegion::reset_alloc_metadata() {
330 _tlab_allocs = 0;
331 _gclab_allocs = 0;
332 _shared_allocs = 0;
333 _seqnum_first_alloc_mutator = 0;
334 _seqnum_last_alloc_mutator = 0;
335 _seqnum_first_alloc_gc = 0;
336 _seqnum_last_alloc_gc = 0;
337 }
338
662 }
663
664 void ShenandoahHeapRegion::do_commit() {
665 if (!_heap->is_heap_region_special() && !os::commit_memory((char *) _reserved.start(), _reserved.byte_size(), false)) {
666 report_java_out_of_memory("Unable to commit region");
667 }
668 if (!_heap->commit_bitmap_slice(this)) {
669 report_java_out_of_memory("Unable to commit bitmaps for region");
670 }
671 _heap->increase_committed(ShenandoahHeapRegion::region_size_bytes());
672 }
673
674 void ShenandoahHeapRegion::do_uncommit() {
675 if (!_heap->is_heap_region_special() && !os::uncommit_memory((char *) _reserved.start(), _reserved.byte_size())) {
676 report_java_out_of_memory("Unable to uncommit region");
677 }
678 if (!_heap->uncommit_bitmap_slice(this)) {
679 report_java_out_of_memory("Unable to uncommit bitmaps for region");
680 }
681 _heap->decrease_committed(ShenandoahHeapRegion::region_size_bytes());
682 }
683
684 void ShenandoahHeapRegion::set_state(RegionState to) {
685 EventShenandoahHeapRegionStateChange evt;
686 if (evt.should_commit()){
687 evt.set_index(region_number());
688 evt.set_start((uintptr_t)bottom());
689 evt.set_used(used());
690 evt.set_from(_state);
691 evt.set_to(to);
692 evt.commit();
693 }
694 _state = to;
695 }
|