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