heapRegionSet.hpp revision 9727:f944761a3ce3
1/*
2 * Copyright (c) 2011, 2015, 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_VM_GC_G1_HEAPREGIONSET_HPP
26#define SHARE_VM_GC_G1_HEAPREGIONSET_HPP
27
28#include "gc/g1/heapRegion.hpp"
29
30#define assert_heap_region_set(p, message)                        \
31  do {                                                            \
32    assert((p), "[%s] %s ln: %u cy: " SIZE_FORMAT,                \
33           name(), message, length(), total_capacity_bytes());    \
34  } while (0)
35
36#define guarantee_heap_region_set(p, message)                     \
37  do {                                                            \
38    guarantee((p), "[%s] %s ln: %u cy: " SIZE_FORMAT,             \
39              name(), message, length(), total_capacity_bytes()); \
40  } while (0)
41
42#define assert_free_region_list(p, message)                                              \
43  do {                                                                                   \
44    assert((p), "[%s] %s ln: %u cy: " SIZE_FORMAT " hd: " PTR_FORMAT " tl: " PTR_FORMAT, \
45           name(), message, length(), total_capacity_bytes(), p2i(_head), p2i(_tail));   \
46  } while (0)
47
48
49// Set verification will be forced either if someone defines
50// HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which
51// asserts are compiled in.
52#ifndef HEAP_REGION_SET_FORCE_VERIFY
53#define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
54#endif // HEAP_REGION_SET_FORCE_VERIFY
55
56class HRSMtSafeChecker : public CHeapObj<mtGC> {
57public:
58  virtual void check() = 0;
59};
60
61class MasterFreeRegionListMtSafeChecker    : public HRSMtSafeChecker { public: void check(); };
62class SecondaryFreeRegionListMtSafeChecker : public HRSMtSafeChecker { public: void check(); };
63class HumongousRegionSetMtSafeChecker      : public HRSMtSafeChecker { public: void check(); };
64class OldRegionSetMtSafeChecker            : public HRSMtSafeChecker { public: void check(); };
65
66class HeapRegionSetCount VALUE_OBJ_CLASS_SPEC {
67  friend class VMStructs;
68  uint   _length;
69  size_t _capacity;
70
71public:
72  HeapRegionSetCount() : _length(0), _capacity(0) { }
73
74  const uint   length()   const { return _length;   }
75  const size_t capacity() const { return _capacity; }
76
77  void increment(uint length_to_add, size_t capacity_to_add) {
78    _length += length_to_add;
79    _capacity += capacity_to_add;
80  }
81
82  void decrement(const uint length_to_remove, const size_t capacity_to_remove) {
83    _length -= length_to_remove;
84    _capacity -= capacity_to_remove;
85  }
86};
87
88// Base class for all the classes that represent heap region sets. It
89// contains the basic attributes that each set needs to maintain
90// (e.g., length, region num, used bytes sum) plus any shared
91// functionality (e.g., verification).
92
93class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
94  friend class VMStructs;
95private:
96  bool _is_humongous;
97  bool _is_free;
98  HRSMtSafeChecker* _mt_safety_checker;
99
100protected:
101  // The number of regions added to the set. If the set contains
102  // only humongous regions, this reflects only 'starts humongous'
103  // regions and does not include 'continues humongous' ones.
104  HeapRegionSetCount _count;
105
106  const char* _name;
107
108  bool _verify_in_progress;
109
110  // verify_region() is used to ensure that the contents of a region
111  // added to / removed from a set are consistent.
112  void verify_region(HeapRegion* hr) PRODUCT_RETURN;
113
114  // Indicates whether all regions in the set should be humongous or
115  // not. Only used during verification.
116  bool regions_humongous() { return _is_humongous; }
117
118  // Indicates whether all regions in the set should be free or
119  // not. Only used during verification.
120  bool regions_free() { return _is_free; }
121
122  void check_mt_safety() {
123    if (_mt_safety_checker != NULL) {
124      _mt_safety_checker->check();
125    }
126  }
127
128  HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker);
129
130public:
131  const char* name() { return _name; }
132
133  uint length() const { return _count.length(); }
134
135  bool is_empty() { return _count.length() == 0; }
136
137  size_t total_capacity_bytes() {
138    return _count.capacity();
139  }
140
141  // It updates the fields of the set to reflect hr being added to
142  // the set and tags the region appropriately.
143  inline void add(HeapRegion* hr);
144
145  // It updates the fields of the set to reflect hr being removed
146  // from the set and tags the region appropriately.
147  inline void remove(HeapRegion* hr);
148
149  virtual void verify();
150  void verify_start();
151  void verify_next_region(HeapRegion* hr);
152  void verify_end();
153
154#if HEAP_REGION_SET_FORCE_VERIFY
155  void verify_optional() {
156    verify();
157  }
158#else // HEAP_REGION_SET_FORCE_VERIFY
159  void verify_optional() { }
160#endif // HEAP_REGION_SET_FORCE_VERIFY
161
162  virtual void print_on(outputStream* out, bool print_contents = false);
163};
164
165#define hrs_assert_sets_match(_set1_, _set2_)                                  \
166  do {                                                                         \
167    assert(((_set1_)->regions_humongous() == (_set2_)->regions_humongous()) && \
168           ((_set1_)->regions_free() == (_set2_)->regions_free()),             \
169           "the contents of set %s and set %s should match",                   \
170           (_set1_)->name(),                                                   \
171           (_set2_)->name());                                                  \
172  } while (0)
173
174// This class represents heap region sets whose members are not
175// explicitly tracked. It's helpful to group regions using such sets
176// so that we can reason about all the region groups in the heap using
177// the same interface (namely, the HeapRegionSetBase API).
178
179class HeapRegionSet : public HeapRegionSetBase {
180public:
181  HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker):
182    HeapRegionSetBase(name, humongous, false /* free */, mt_safety_checker) { }
183
184  void bulk_remove(const HeapRegionSetCount& removed) {
185    _count.decrement(removed.length(), removed.capacity());
186  }
187};
188
189// A set that links all the regions added to it in a doubly-linked
190// sorted list. We should try to avoid doing operations that iterate over
191// such lists in performance critical paths. Typically we should
192// add / remove one region at a time or concatenate two lists.
193
194class FreeRegionListIterator;
195
196class FreeRegionList : public HeapRegionSetBase {
197  friend class FreeRegionListIterator;
198
199private:
200  HeapRegion* _head;
201  HeapRegion* _tail;
202
203  // _last is used to keep track of where we added an element the last
204  // time. It helps to improve performance when adding several ordered items in a row.
205  HeapRegion* _last;
206
207  static uint _unrealistically_long_length;
208
209  inline HeapRegion* remove_from_head_impl();
210  inline HeapRegion* remove_from_tail_impl();
211
212protected:
213  // See the comment for HeapRegionSetBase::clear()
214  virtual void clear();
215
216public:
217  FreeRegionList(const char* name, HRSMtSafeChecker* mt_safety_checker = NULL):
218    HeapRegionSetBase(name, false /* humongous */, true /* empty */, mt_safety_checker) {
219    clear();
220  }
221
222  void verify_list();
223
224#ifdef ASSERT
225  bool contains(HeapRegion* hr) const {
226    return hr->containing_set() == this;
227  }
228#endif
229
230  static void set_unrealistically_long_length(uint len);
231
232  // Add hr to the list. The region should not be a member of another set.
233  // Assumes that the list is ordered and will preserve that order. The order
234  // is determined by hrm_index.
235  inline void add_ordered(HeapRegion* hr);
236
237  // Removes from head or tail based on the given argument.
238  HeapRegion* remove_region(bool from_head);
239
240  // Merge two ordered lists. The result is also ordered. The order is
241  // determined by hrm_index.
242  void add_ordered(FreeRegionList* from_list);
243
244  // It empties the list by removing all regions from it.
245  void remove_all();
246
247  // Remove all (contiguous) regions from first to first + num_regions -1 from
248  // this list.
249  // Num_regions must be > 1.
250  void remove_starting_at(HeapRegion* first, uint num_regions);
251
252  virtual void verify();
253};
254
255// Iterator class that provides a convenient way to iterate over the
256// regions of a FreeRegionList.
257
258class FreeRegionListIterator : public StackObj {
259private:
260  FreeRegionList* _list;
261  HeapRegion*     _curr;
262
263public:
264  bool more_available() {
265    return _curr != NULL;
266  }
267
268  HeapRegion* get_next() {
269    assert(more_available(),
270           "get_next() should be called when more regions are available");
271
272    // If we are going to introduce a count in the iterator we should
273    // do the "cycle" check.
274
275    HeapRegion* hr = _curr;
276    _list->verify_region(hr);
277    _curr = hr->next();
278    return hr;
279  }
280
281  FreeRegionListIterator(FreeRegionList* list) : _curr(NULL), _list(list) {
282    _curr = list->_head;
283  }
284};
285
286#endif // SHARE_VM_GC_G1_HEAPREGIONSET_HPP
287