1 /*
  2  * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
  3  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
 27 #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
 28 
 29 #include "gc/shared/gc_globals.hpp"
 30 #include "gc/shared/spaceDecorator.hpp"
 31 #include "gc/shenandoah/shenandoahAffiliation.hpp"
 32 #include "gc/shenandoah/shenandoahAgeCensus.hpp"
 33 #include "gc/shenandoah/shenandoahAllocRequest.hpp"
 34 #include "gc/shenandoah/shenandoahAsserts.hpp"
 35 #include "gc/shenandoah/shenandoahHeap.hpp"
 36 #include "gc/shenandoah/shenandoahPadding.hpp"
 37 #include "utilities/sizes.hpp"
 38 
 39 class VMStructs;
 40 class ShenandoahHeapRegionStateConstant;
 41 
 42 class ShenandoahHeapRegion {
 43   friend class VMStructs;
 44   friend class ShenandoahHeapRegionStateConstant;
 45 private:
 46   /*
 47     Region state is described by a state machine. Transitions are guarded by
 48     heap lock, which allows changing the state of several regions atomically.
 49     Region states can be logically aggregated in groups.
 50 
 51       "Empty":
 52       .................................................................
 53       .                                                               .
 54       .                                                               .
 55       .         Uncommitted  <-------  Committed <------------------------\
 56       .              |                     |                          .   |
 57       .              \---------v-----------/                          .   |
 58       .                        |                                      .   |
 59       .........................|.......................................   |
 60                                |                                          |
 61       "Active":                |                                          |
 62       .........................|.......................................   |
 63       .                        |                                      .   |
 64       .      /-----------------^-------------------\                  .   |
 65       .      |                                     |                  .   |
 66       .      v                                     v    "Humongous":  .   |
 67       .   Regular ---\-----\     ..................O................  .   |
 68       .     |  ^     |     |     .                 |               .  .   |
 69       .     |  |     |     |     .                 *---------\     .  .   |
 70       .     v  |     |     |     .                 v         v     .  .   |
 71       .    Pinned  Cset    |     .  HStart <--> H/Start   H/Cont   .  .   |
 72       .       ^    / |     |     .  Pinned         v         |     .  .   |
 73       .       |   /  |     |     .                 *<--------/     .  .   |
 74       .       |  v   |     |     .                 |               .  .   |
 75       .  CsetPinned  |     |     ..................O................  .   |
 76       .              |     |                       |                  .   |
 77       .              \-----\---v-------------------/                  .   |
 78       .                        |                                      .   |
 79       .........................|.......................................   |
 80                                |                                          |
 81       "Trash":                 |                                          |
 82       .........................|.......................................   |
 83       .                        |                                      .   |
 84       .                        v                                      .   |
 85       .                      Trash ---------------------------------------/
 86       .                                                               .
 87       .                                                               .
 88       .................................................................
 89 
 90     Transition from "Empty" to "Active" is first allocation. It can go from {Uncommitted, Committed}
 91     to {Regular, "Humongous"}. The allocation may happen in Regular regions too, but not in Humongous.
 92 
 93     Transition from "Active" to "Trash" is reclamation. It can go from CSet during the normal cycle,
 94     and from {Regular, "Humongous"} for immediate reclamation. The existence of Trash state allows
 95     quick reclamation without actual cleaning up.
 96 
 97     Transition from "Trash" to "Empty" is recycling. It cleans up the regions and corresponding metadata.
 98     Can be done asynchronously and in bulk.
 99 
100     Note how internal transitions disallow logic bugs:
101       a) No region can go Empty, unless properly reclaimed/recycled;
102       b) No region can go Uncommitted, unless reclaimed/recycled first;
103       c) Only Regular regions can go to CSet;
104       d) Pinned cannot go Trash, thus it could never be reclaimed until unpinned;
105       e) Pinned cannot go CSet, thus it never moves;
106       f) Humongous cannot be used for regular allocations;
107       g) Humongous cannot go CSet, thus it never moves;
108       h) Humongous start can go pinned, and thus can be protected from moves (humongous continuations should
109          follow associated humongous starts, not pinnable/movable by themselves);
110       i) Empty cannot go Trash, avoiding useless work;
111       j) ...
112    */
113 
114   enum RegionState {
115     _empty_uncommitted,       // region is empty and has memory uncommitted
116     _empty_committed,         // region is empty and has memory committed
117     _regular,                 // region is for regular allocations
118     _humongous_start,         // region is the humongous start
119     _humongous_cont,          // region is the humongous continuation
120     _pinned_humongous_start,  // region is both humongous start and pinned
121     _cset,                    // region is in collection set
122     _pinned,                  // region is pinned
123     _pinned_cset,             // region is pinned and in cset (evac failure path)
124     _trash,                   // region contains only trash
125     _REGION_STATES_NUM        // last
126   };
127 
128 public:
129   static const char* region_state_to_string(RegionState s) {
130     switch (s) {
131       case _empty_uncommitted:       return "Empty Uncommitted";
132       case _empty_committed:         return "Empty Committed";
133       case _regular:                 return "Regular";
134       case _humongous_start:         return "Humongous Start";
135       case _humongous_cont:          return "Humongous Continuation";
136       case _pinned_humongous_start:  return "Humongous Start, Pinned";
137       case _cset:                    return "Collection Set";
138       case _pinned:                  return "Pinned";
139       case _pinned_cset:             return "Collection Set, Pinned";
140       case _trash:                   return "Trash";
141       default:
142         ShouldNotReachHere();
143         return "";
144     }
145   }
146 
147 private:
148   // This method protects from accidental changes in enum order:
149   int region_state_to_ordinal(RegionState s) const {
150     switch (s) {
151       case _empty_uncommitted:      return 0;
152       case _empty_committed:        return 1;
153       case _regular:                return 2;
154       case _humongous_start:        return 3;
155       case _humongous_cont:         return 4;
156       case _cset:                   return 5;
157       case _pinned:                 return 6;
158       case _trash:                  return 7;
159       case _pinned_cset:            return 8;
160       case _pinned_humongous_start: return 9;
161       default:
162         ShouldNotReachHere();
163         return -1;
164     }
165   }
166 
167   void report_illegal_transition(const char* method);
168   void recycle_internal();
169 
170 public:
171   static int region_states_num() {
172     return _REGION_STATES_NUM;
173   }
174 
175   // Allowed transitions from the outside code:
176   void make_regular_allocation(ShenandoahAffiliation affiliation);
177   void make_affiliated_maybe();
178   void make_regular_bypass();
179   void make_humongous_start();
180   void make_humongous_cont();
181   void make_humongous_start_bypass(ShenandoahAffiliation affiliation);
182   void make_humongous_cont_bypass(ShenandoahAffiliation affiliation);
183   void make_pinned();
184   void make_unpinned();
185   void make_cset();
186   void make_trash();
187   void make_trash_immediate();
188   void make_empty();
189   void make_uncommitted();
190   void make_committed_bypass();
191 
192   // Primitive state predicates
193   bool is_empty_uncommitted()      const { return state() == _empty_uncommitted; }
194   bool is_empty_committed()        const { return state() == _empty_committed; }
195   bool is_regular()                const { return state() == _regular; }
196   bool is_humongous_continuation() const { return state() == _humongous_cont; }
197   bool is_regular_pinned()         const { return state() == _pinned; }
198   bool is_trash()                  const { return state() == _trash; }
199 
200   // Derived state predicates (boolean combinations of individual states)
201   bool static is_empty_state(RegionState state) { return state == _empty_committed || state == _empty_uncommitted; }
202   bool static is_humongous_start_state(RegionState state) { return state == _humongous_start || state == _pinned_humongous_start; }
203   bool is_empty()                  const { return is_empty_state(this->state()); }
204   bool is_active()                 const { auto cur_state = state(); return !is_empty_state(cur_state) && cur_state != _trash; }
205   bool is_humongous_start()        const { return is_humongous_start_state(state()); }
206   bool is_humongous()              const { auto cur_state = state(); return is_humongous_start_state(cur_state) || cur_state == _humongous_cont; }
207   bool is_committed()              const { return !is_empty_uncommitted(); }
208   bool is_cset()                   const { auto cur_state = state(); return cur_state == _cset || cur_state == _pinned_cset; }
209   bool is_pinned()                 const { auto cur_state = state(); return cur_state == _pinned || cur_state == _pinned_cset || cur_state == _pinned_humongous_start; }
210 
211   inline bool is_young() const;
212   inline bool is_old() const;
213   inline bool is_affiliated() const;
214 
215   // Macro-properties:
216   bool is_alloc_allowed()          const { auto cur_state = state(); return is_empty_state(cur_state) || cur_state == _regular || cur_state == _pinned; }
217   bool is_stw_move_allowed()       const { auto cur_state = state(); return cur_state == _regular || cur_state == _cset || (ShenandoahHumongousMoves && cur_state == _humongous_start); }
218 
219   RegionState state()              const { return Atomic::load(&_state); }
220   int  state_ordinal()             const { return region_state_to_ordinal(state()); }
221 
222   void record_pin();
223   void record_unpin();
224   size_t pin_count() const;
225 
226 private:
227   static size_t RegionCount;
228   static size_t RegionSizeBytes;
229   static size_t RegionSizeWords;
230   static size_t RegionSizeBytesShift;
231   static size_t RegionSizeWordsShift;
232   static size_t RegionSizeBytesMask;
233   static size_t RegionSizeWordsMask;
234   static size_t MaxTLABSizeBytes;
235   static size_t MaxTLABSizeWords;
236 
237   // Never updated fields
238   size_t const _index;
239   HeapWord* const _bottom;
240   HeapWord* const _end;
241 
242   // Rarely updated fields
243   HeapWord* _new_top;
244   double _empty_time;
245 
246   HeapWord* _top_before_promoted;
247 
248   // Seldom updated fields
249   volatile RegionState _state;
250   HeapWord* _coalesce_and_fill_boundary; // for old regions not selected as collection set candidates.
251 
252   // Frequently updated fields
253   HeapWord* _top;
254 
255   size_t _tlab_allocs;
256   size_t _gclab_allocs;
257   size_t _plab_allocs;
258 
259   volatile size_t _live_data;
260   volatile size_t _critical_pins;
261 
262   HeapWord* volatile _update_watermark;
263 
264   uint _age;
265   CENSUS_NOISE(uint _youth;)   // tracks epochs of retrograde ageing (rejuvenation)
266 
267   ShenandoahSharedFlag _recycling; // Used to indicate that the region is being recycled; see try_recycle*().
268 
269   bool _needs_bitmap_reset;
270 
271 public:
272   ShenandoahHeapRegion(HeapWord* start, size_t index, bool committed);
273 
274   static const size_t MIN_NUM_REGIONS = 10;
275 
276   // Return adjusted max heap size
277   static size_t setup_sizes(size_t max_heap_size);
278 
279   double empty_time() {
280     return _empty_time;
281   }
282 
283   inline static size_t required_regions(size_t bytes) {
284     return (bytes + ShenandoahHeapRegion::region_size_bytes() - 1) >> ShenandoahHeapRegion::region_size_bytes_shift();
285   }
286 
287   inline static bool requires_humongous(size_t words) {
288     return words > ShenandoahHeapRegion::RegionSizeWords;
289   }
290 
291   inline static size_t region_count() {
292     return ShenandoahHeapRegion::RegionCount;
293   }
294 
295   inline static size_t region_size_bytes() {
296     return ShenandoahHeapRegion::RegionSizeBytes;
297   }
298 
299   inline static size_t region_size_words() {
300     return ShenandoahHeapRegion::RegionSizeWords;
301   }
302 
303   inline static size_t region_size_bytes_shift() {
304     return ShenandoahHeapRegion::RegionSizeBytesShift;
305   }
306 
307   inline static size_t region_size_words_shift() {
308     return ShenandoahHeapRegion::RegionSizeWordsShift;
309   }
310 
311   inline static size_t region_size_bytes_mask() {
312     return ShenandoahHeapRegion::RegionSizeBytesMask;
313   }
314 
315   inline static size_t region_size_words_mask() {
316     return ShenandoahHeapRegion::RegionSizeWordsMask;
317   }
318 
319   // Convert to jint with sanity checking
320   inline static jint region_size_bytes_jint() {
321     assert (ShenandoahHeapRegion::RegionSizeBytes <= (size_t)max_jint, "sanity");
322     return (jint)ShenandoahHeapRegion::RegionSizeBytes;
323   }
324 
325   // Convert to jint with sanity checking
326   inline static jint region_size_words_jint() {
327     assert (ShenandoahHeapRegion::RegionSizeWords <= (size_t)max_jint, "sanity");
328     return (jint)ShenandoahHeapRegion::RegionSizeWords;
329   }
330 
331   // Convert to jint with sanity checking
332   inline static jint region_size_bytes_shift_jint() {
333     assert (ShenandoahHeapRegion::RegionSizeBytesShift <= (size_t)max_jint, "sanity");
334     return (jint)ShenandoahHeapRegion::RegionSizeBytesShift;
335   }
336 
337   // Convert to jint with sanity checking
338   inline static jint region_size_words_shift_jint() {
339     assert (ShenandoahHeapRegion::RegionSizeWordsShift <= (size_t)max_jint, "sanity");
340     return (jint)ShenandoahHeapRegion::RegionSizeWordsShift;
341   }
342 
343   inline static size_t max_tlab_size_bytes() {
344     return ShenandoahHeapRegion::MaxTLABSizeBytes;
345   }
346 
347   inline static size_t max_tlab_size_words() {
348     return ShenandoahHeapRegion::MaxTLABSizeWords;
349   }
350 
351   inline size_t index() const {
352     return _index;
353   }
354 
355   inline void save_top_before_promote();
356   inline HeapWord* get_top_before_promote() const { return _top_before_promoted; }
357   inline void restore_top_before_promote();
358   inline size_t garbage_before_padded_for_promote() const;
359 
360   // If next available memory is not aligned on address that is multiple of alignment, fill the empty space
361   // so that returned object is aligned on an address that is a multiple of alignment_in_bytes.  Requested
362   // size is in words.  It is assumed that this->is_old().  A pad object is allocated, filled, and registered
363   // if necessary to assure the new allocation is properly aligned.  Return nullptr if memory is not available.
364   inline HeapWord* allocate_aligned(size_t word_size, ShenandoahAllocRequest &req, size_t alignment_in_bytes);
365 
366   // Allocation (return nullptr if full)
367   inline HeapWord* allocate(size_t word_size, const ShenandoahAllocRequest& req);
368 
369   inline void clear_live_data();
370   void set_live_data(size_t s);
371 
372   // Increase live data for newly allocated region
373   inline void increase_live_data_alloc_words(size_t s);
374 
375   // Increase live data for region scanned with GC
376   inline void increase_live_data_gc_words(size_t s);
377 
378   inline bool has_live() const;
379   inline size_t get_live_data_bytes() const;
380   inline size_t get_live_data_words() const;
381 
382   inline size_t garbage() const;
383 
384   void print_on(outputStream* st) const;
385 
386   void try_recycle_under_lock();
387 
388   void try_recycle();
389 
390   inline void begin_preemptible_coalesce_and_fill() {
391     _coalesce_and_fill_boundary = _bottom;
392   }
393 
394   inline void end_preemptible_coalesce_and_fill() {
395     _coalesce_and_fill_boundary = _end;
396   }
397 
398   inline void suspend_coalesce_and_fill(HeapWord* next_focus) {
399     _coalesce_and_fill_boundary = next_focus;
400   }
401 
402   inline HeapWord* resume_coalesce_and_fill() {
403     return _coalesce_and_fill_boundary;
404   }
405 
406   // Coalesce contiguous spans of garbage objects by filling header and registering start locations with remembered set.
407   // This is used by old-gen GC following concurrent marking to make old-gen HeapRegions parsable. Old regions must be
408   // parsable because the mark bitmap is not reliable during the concurrent old mark.
409   // Return true iff region is completely coalesced and filled.  Returns false if cancelled before task is complete.
410   bool oop_coalesce_and_fill(bool cancellable);
411 
412   // Invoke closure on every reference contained within the humongous object that spans this humongous
413   // region if the reference is contained within a DIRTY card and the reference is no more than words following
414   // start within the humongous object.
415   void oop_iterate_humongous_slice_dirty(OopIterateClosure* cl, HeapWord* start, size_t words, bool write_table) const;
416 
417   // Invoke closure on every reference contained within the humongous object starting from start and
418   // ending at start + words.
419   void oop_iterate_humongous_slice_all(OopIterateClosure* cl, HeapWord* start, size_t words) const;
420 
421   HeapWord* block_start(const void* p) const;
422   size_t block_size(const HeapWord* p) const;
423   bool block_is_obj(const HeapWord* p) const { return p < top(); }
424 
425   // Find humongous start region that this region belongs to
426   ShenandoahHeapRegion* humongous_start_region() const;
427 
428   HeapWord* top() const         { return _top;     }
429   void set_top(HeapWord* v)     { _top = v;        }
430 
431   HeapWord* new_top() const     { return _new_top; }
432   void set_new_top(HeapWord* v) { _new_top = v;    }
433 
434   HeapWord* bottom() const      { return _bottom;  }
435   HeapWord* end() const         { return _end;     }
436 
437   size_t capacity() const       { return byte_size(bottom(), end()); }
438   size_t used() const           { return byte_size(bottom(), top()); }
439   size_t used_before_promote() const { return byte_size(bottom(), get_top_before_promote()); }
440   size_t free() const           { return byte_size(top(),    end()); }
441 
442   // Does this region contain this address?
443   bool contains(HeapWord* p) const {
444     return (bottom() <= p) && (p < top());
445   }
446 
447   inline void adjust_alloc_metadata(ShenandoahAllocRequest::Type type, size_t);
448   void reset_alloc_metadata();
449   size_t get_shared_allocs() const;
450   size_t get_tlab_allocs() const;
451   size_t get_gclab_allocs() const;
452   size_t get_plab_allocs() const;
453 
454   inline HeapWord* get_update_watermark() const;
455   inline void set_update_watermark(HeapWord* w);
456   inline void set_update_watermark_at_safepoint(HeapWord* w);
457 
458   inline ShenandoahAffiliation affiliation() const;
459   inline const char* affiliation_name() const;
460 
461   void set_affiliation(ShenandoahAffiliation new_affiliation);
462 
463   // Region ageing and rejuvenation
464   uint age() const { return _age; }
465   CENSUS_NOISE(uint youth() const { return _youth; })
466 
467   void increment_age() {
468     const uint max_age = markWord::max_age;
469     assert(_age <= max_age, "Error");
470     if (_age++ >= max_age) {
471       _age = max_age;   // clamp
472     }
473   }
474 
475   void reset_age() {
476     CENSUS_NOISE(_youth += _age;)
477     _age = 0;
478   }
479 
480   CENSUS_NOISE(void clear_youth() { _youth = 0; })
481 
482   inline bool need_bitmap_reset() const {
483     return _needs_bitmap_reset;
484   }
485 
486   inline void set_needs_bitmap_reset() {
487     _needs_bitmap_reset = true;
488   }
489 
490   inline void unset_needs_bitmap_reset() {
491     _needs_bitmap_reset = false;
492   }
493 
494 private:
495   void decrement_humongous_waste() const;
496   void do_commit();
497   void do_uncommit();
498 
499   inline void internal_increase_live_data(size_t s);
500 
501   void set_state(RegionState to);
502 };
503 
504 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP