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