src/share/vm/gc_implementation/g1/heapRegionSet.hpp

Wed, 19 Jan 2011 19:30:42 -0500

author
tonyp
date
Wed, 19 Jan 2011 19:30:42 -0500
changeset 2472
0fa27f37d4d4
child 2643
1216415d8e35
permissions
-rw-r--r--

6977804: G1: remove the zero-filling thread
Summary: This changeset removes the zero-filling thread from G1 and collapses the two free region lists we had before (the "free" and "unclean" lists) into one. The new free list uses the new heap region sets / lists abstractions that we'll ultimately use it to keep track of all regions in the heap. A heap region set was also introduced for the humongous regions. Finally, this change increases the concurrency between the thread that completes freeing regions (after a cleanup pause) and the rest of the system (before we'd have to wait for said thread to complete before allocating a new region). The changest also includes a lot of refactoring and code simplification.
Reviewed-by: jcoomes, johnc

tonyp@2472 1 /*
tonyp@2472 2 * copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
tonyp@2472 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tonyp@2472 4 *
tonyp@2472 5 * This code is free software; you can redistribute it and/or modify it
tonyp@2472 6 * under the terms of the GNU General Public License version 2 only, as
tonyp@2472 7 * published by the Free Software Foundation.
tonyp@2472 8 *
tonyp@2472 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tonyp@2472 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tonyp@2472 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tonyp@2472 12 * version 2 for more details (a copy is included in the LICENSE file that
tonyp@2472 13 * accompanied this code).
tonyp@2472 14 *
tonyp@2472 15 * You should have received a copy of the GNU General Public License version
tonyp@2472 16 * 2 along with this work; if not, write to the Free Software Foundation,
tonyp@2472 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tonyp@2472 18 *
tonyp@2472 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tonyp@2472 20 * or visit www.oracle.com if you need additional information or have any
tonyp@2472 21 * questions.
tonyp@2472 22 *
tonyp@2472 23 */
tonyp@2472 24
tonyp@2472 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
tonyp@2472 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
tonyp@2472 27
tonyp@2472 28 #include "gc_implementation/g1/heapRegion.hpp"
tonyp@2472 29
tonyp@2472 30 // Large buffer for some cases where the output might be larger than normal.
tonyp@2472 31 #define HRL_ERR_MSG_BUFSZ 512
tonyp@2472 32 typedef FormatBuffer<HRL_ERR_MSG_BUFSZ> hrl_err_msg;
tonyp@2472 33
tonyp@2472 34 // Set verification will be forced either if someone defines
tonyp@2472 35 // HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which
tonyp@2472 36 // asserts are compiled in.
tonyp@2472 37 #ifndef HEAP_REGION_SET_FORCE_VERIFY
tonyp@2472 38 #define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
tonyp@2472 39 #endif // HEAP_REGION_SET_FORCE_VERIFY
tonyp@2472 40
tonyp@2472 41 //////////////////// HeapRegionSetBase ////////////////////
tonyp@2472 42
tonyp@2472 43 // Base class for all the classes that represent heap region sets. It
tonyp@2472 44 // contains the basic attributes that each set needs to maintain
tonyp@2472 45 // (e.g., length, region num, used bytes sum) plus any shared
tonyp@2472 46 // functionality (e.g., verification).
tonyp@2472 47
tonyp@2472 48 class hrl_ext_msg;
tonyp@2472 49
tonyp@2472 50 class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
tonyp@2472 51 friend class hrl_ext_msg;
tonyp@2472 52
tonyp@2472 53 protected:
tonyp@2472 54 static size_t calculate_region_num(HeapRegion* hr);
tonyp@2472 55
tonyp@2472 56 static size_t _unrealistically_long_length;
tonyp@2472 57
tonyp@2472 58 // The number of regions added to the set. If the set contains
tonyp@2472 59 // only humongous regions, this reflects only 'starts humongous'
tonyp@2472 60 // regions and does not include 'continues humongous' ones.
tonyp@2472 61 size_t _length;
tonyp@2472 62
tonyp@2472 63 // The total number of regions represented by the set. If the set
tonyp@2472 64 // does not contain humongous regions, this should be the same as
tonyp@2472 65 // _length. If the set contains only humongous regions, this will
tonyp@2472 66 // include the 'continues humongous' regions.
tonyp@2472 67 size_t _region_num;
tonyp@2472 68
tonyp@2472 69 // We don't keep track of the total capacity explicitly, we instead
tonyp@2472 70 // recalculate it based on _region_num and the heap region size.
tonyp@2472 71
tonyp@2472 72 // The sum of used bytes in the all the regions in the set.
tonyp@2472 73 size_t _total_used_bytes;
tonyp@2472 74
tonyp@2472 75 const char* _name;
tonyp@2472 76
tonyp@2472 77 bool _verify_in_progress;
tonyp@2472 78 size_t _calc_length;
tonyp@2472 79 size_t _calc_region_num;
tonyp@2472 80 size_t _calc_total_capacity_bytes;
tonyp@2472 81 size_t _calc_total_used_bytes;
tonyp@2472 82
tonyp@2472 83 // verify_region() is used to ensure that the contents of a region
tonyp@2472 84 // added to / removed from a set are consistent. Different sets
tonyp@2472 85 // make different assumptions about the regions added to them. So
tonyp@2472 86 // each set can override verify_region_extra(), which is called
tonyp@2472 87 // from verify_region(), and do any extra verification it needs to
tonyp@2472 88 // perform in that.
tonyp@2472 89 virtual const char* verify_region_extra(HeapRegion* hr) { return NULL; }
tonyp@2472 90 bool verify_region(HeapRegion* hr,
tonyp@2472 91 HeapRegionSetBase* expected_containing_set);
tonyp@2472 92
tonyp@2472 93 // Indicates whether all regions in the set should be humongous or
tonyp@2472 94 // not. Only used during verification.
tonyp@2472 95 virtual bool regions_humongous() = 0;
tonyp@2472 96
tonyp@2472 97 // Indicates whether all regions in the set should be empty or
tonyp@2472 98 // not. Only used during verification.
tonyp@2472 99 virtual bool regions_empty() = 0;
tonyp@2472 100
tonyp@2472 101 // Subclasses can optionally override this to do MT safety protocol
tonyp@2472 102 // checks. It is called in an assert from all methods that perform
tonyp@2472 103 // updates on the set (and subclasses should also call it too).
tonyp@2472 104 virtual bool check_mt_safety() { return true; }
tonyp@2472 105
tonyp@2472 106 // fill_in_ext_msg() writes the the values of the set's attributes
tonyp@2472 107 // in the custom err_msg (hrl_ext_msg). fill_in_ext_msg_extra()
tonyp@2472 108 // allows subclasses to append further information.
tonyp@2472 109 virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg) { }
tonyp@2472 110 void fill_in_ext_msg(hrl_ext_msg* msg, const char* message);
tonyp@2472 111
tonyp@2472 112 // It updates the fields of the set to reflect hr being added to
tonyp@2472 113 // the set.
tonyp@2472 114 inline void update_for_addition(HeapRegion* hr);
tonyp@2472 115
tonyp@2472 116 // It updates the fields of the set to reflect hr being added to
tonyp@2472 117 // the set and tags the region appropriately.
tonyp@2472 118 inline void add_internal(HeapRegion* hr);
tonyp@2472 119
tonyp@2472 120 // It updates the fields of the set to reflect hr being removed
tonyp@2472 121 // from the set.
tonyp@2472 122 inline void update_for_removal(HeapRegion* hr);
tonyp@2472 123
tonyp@2472 124 // It updates the fields of the set to reflect hr being removed
tonyp@2472 125 // from the set and tags the region appropriately.
tonyp@2472 126 inline void remove_internal(HeapRegion* hr);
tonyp@2472 127
tonyp@2472 128 // It clears all the fields of the sets. Note: it will not iterate
tonyp@2472 129 // over the set and remove regions from it. It assumes that the
tonyp@2472 130 // caller has already done so. It will literally just clear the fields.
tonyp@2472 131 virtual void clear();
tonyp@2472 132
tonyp@2472 133 HeapRegionSetBase(const char* name);
tonyp@2472 134
tonyp@2472 135 public:
tonyp@2472 136 static void set_unrealistically_long_length(size_t len);
tonyp@2472 137
tonyp@2472 138 const char* name() { return _name; }
tonyp@2472 139
tonyp@2472 140 size_t length() { return _length; }
tonyp@2472 141
tonyp@2472 142 bool is_empty() { return _length == 0; }
tonyp@2472 143
tonyp@2472 144 size_t region_num() { return _region_num; }
tonyp@2472 145
tonyp@2472 146 size_t total_capacity_bytes() {
tonyp@2472 147 return region_num() << HeapRegion::LogOfHRGrainBytes;
tonyp@2472 148 }
tonyp@2472 149
tonyp@2472 150 size_t total_used_bytes() { return _total_used_bytes; }
tonyp@2472 151
tonyp@2472 152 virtual void verify();
tonyp@2472 153 void verify_start();
tonyp@2472 154 void verify_next_region(HeapRegion* hr);
tonyp@2472 155 void verify_end();
tonyp@2472 156
tonyp@2472 157 #if HEAP_REGION_SET_FORCE_VERIFY
tonyp@2472 158 void verify_optional() {
tonyp@2472 159 verify();
tonyp@2472 160 }
tonyp@2472 161 #else // HEAP_REGION_SET_FORCE_VERIFY
tonyp@2472 162 void verify_optional() { }
tonyp@2472 163 #endif // HEAP_REGION_SET_FORCE_VERIFY
tonyp@2472 164
tonyp@2472 165 virtual void print_on(outputStream* out, bool print_contents = false);
tonyp@2472 166 };
tonyp@2472 167
tonyp@2472 168 // Customized err_msg for heap region sets. Apart from a
tonyp@2472 169 // assert/guarantee-specific message it also prints out the values of
tonyp@2472 170 // the fields of the associated set. This can be very helpful in
tonyp@2472 171 // diagnosing failures.
tonyp@2472 172
tonyp@2472 173 class hrl_ext_msg : public hrl_err_msg {
tonyp@2472 174 public:
tonyp@2472 175 hrl_ext_msg(HeapRegionSetBase* set, const char* message) : hrl_err_msg("") {
tonyp@2472 176 set->fill_in_ext_msg(this, message);
tonyp@2472 177 }
tonyp@2472 178 };
tonyp@2472 179
tonyp@2472 180 // These two macros are provided for convenience, to keep the uses of
tonyp@2472 181 // these two asserts a bit more concise.
tonyp@2472 182
tonyp@2472 183 #define hrl_assert_mt_safety_ok(_set_) \
tonyp@2472 184 do { \
tonyp@2472 185 assert((_set_)->check_mt_safety(), hrl_ext_msg((_set_), "MT safety")); \
tonyp@2472 186 } while (0)
tonyp@2472 187
tonyp@2472 188 #define hrl_assert_region_ok(_set_, _hr_, _expected_) \
tonyp@2472 189 do { \
tonyp@2472 190 assert((_set_)->verify_region((_hr_), (_expected_)), \
tonyp@2472 191 hrl_ext_msg((_set_), "region verification")); \
tonyp@2472 192 } while (0)
tonyp@2472 193
tonyp@2472 194 //////////////////// HeapRegionSet ////////////////////
tonyp@2472 195
tonyp@2472 196 #define hrl_assert_sets_match(_set1_, _set2_) \
tonyp@2472 197 do { \
tonyp@2472 198 assert(((_set1_)->regions_humongous() == \
tonyp@2472 199 (_set2_)->regions_humongous()) && \
tonyp@2472 200 ((_set1_)->regions_empty() == (_set2_)->regions_empty()), \
tonyp@2472 201 hrl_err_msg("the contents of set %s and set %s should match", \
tonyp@2472 202 (_set1_)->name(), (_set2_)->name())); \
tonyp@2472 203 } while (0)
tonyp@2472 204
tonyp@2472 205 // This class represents heap region sets whose members are not
tonyp@2472 206 // explicitly tracked. It's helpful to group regions using such sets
tonyp@2472 207 // so that we can reason about all the region groups in the heap using
tonyp@2472 208 // the same interface (namely, the HeapRegionSetBase API).
tonyp@2472 209
tonyp@2472 210 class HeapRegionSet : public HeapRegionSetBase {
tonyp@2472 211 protected:
tonyp@2472 212 virtual const char* verify_region_extra(HeapRegion* hr) {
tonyp@2472 213 if (hr->next() != NULL) {
tonyp@2472 214 return "next() should always be NULL as we do not link the regions";
tonyp@2472 215 }
tonyp@2472 216
tonyp@2472 217 return HeapRegionSetBase::verify_region_extra(hr);
tonyp@2472 218 }
tonyp@2472 219
tonyp@2472 220 HeapRegionSet(const char* name) : HeapRegionSetBase(name) {
tonyp@2472 221 clear();
tonyp@2472 222 }
tonyp@2472 223
tonyp@2472 224 public:
tonyp@2472 225 // It adds hr to the set. The region should not be a member of
tonyp@2472 226 // another set.
tonyp@2472 227 inline void add(HeapRegion* hr);
tonyp@2472 228
tonyp@2472 229 // It removes hr from the set. The region should be a member of
tonyp@2472 230 // this set.
tonyp@2472 231 inline void remove(HeapRegion* hr);
tonyp@2472 232
tonyp@2472 233 // It removes a region from the set. Instead of updating the fields
tonyp@2472 234 // of the set to reflect this removal, it accumulates the updates
tonyp@2472 235 // in proxy_set. The idea is that proxy_set is thread-local to
tonyp@2472 236 // avoid multiple threads updating the fields of the set
tonyp@2472 237 // concurrently and having to synchronize. The method
tonyp@2472 238 // update_from_proxy() will update the fields of the set from the
tonyp@2472 239 // proxy_set.
tonyp@2472 240 inline void remove_with_proxy(HeapRegion* hr, HeapRegionSet* proxy_set);
tonyp@2472 241
tonyp@2472 242 // After multiple calls to remove_with_proxy() the updates to the
tonyp@2472 243 // fields of the set are accumulated in proxy_set. This call
tonyp@2472 244 // updates the fields of the set from proxy_set.
tonyp@2472 245 void update_from_proxy(HeapRegionSet* proxy_set);
tonyp@2472 246 };
tonyp@2472 247
tonyp@2472 248 //////////////////// HeapRegionLinkedList ////////////////////
tonyp@2472 249
tonyp@2472 250 // A set that links all the regions added to it in a singly-linked
tonyp@2472 251 // list. We should try to avoid doing operations that iterate over
tonyp@2472 252 // such lists in performance critical paths. Typically we should
tonyp@2472 253 // add / remove one region at a time or concatenate two lists. All
tonyp@2472 254 // those operations are done in constant time.
tonyp@2472 255
tonyp@2472 256 class HeapRegionLinkedListIterator;
tonyp@2472 257
tonyp@2472 258 class HeapRegionLinkedList : public HeapRegionSetBase {
tonyp@2472 259 friend class HeapRegionLinkedListIterator;
tonyp@2472 260
tonyp@2472 261 private:
tonyp@2472 262 HeapRegion* _head;
tonyp@2472 263 HeapRegion* _tail;
tonyp@2472 264
tonyp@2472 265 // These are provided for use by the friend classes.
tonyp@2472 266 HeapRegion* head() { return _head; }
tonyp@2472 267 HeapRegion* tail() { return _tail; }
tonyp@2472 268
tonyp@2472 269 protected:
tonyp@2472 270 virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg);
tonyp@2472 271
tonyp@2472 272 // See the comment for HeapRegionSetBase::clear()
tonyp@2472 273 virtual void clear();
tonyp@2472 274
tonyp@2472 275 HeapRegionLinkedList(const char* name) : HeapRegionSetBase(name) {
tonyp@2472 276 clear();
tonyp@2472 277 }
tonyp@2472 278
tonyp@2472 279 public:
tonyp@2472 280 // It adds hr to the list as the new tail. The region should not be
tonyp@2472 281 // a member of another set.
tonyp@2472 282 inline void add_as_tail(HeapRegion* hr);
tonyp@2472 283
tonyp@2472 284 // It removes and returns the head of the list. It assumes that the
tonyp@2472 285 // list is not empty so it will return a non-NULL value.
tonyp@2472 286 inline HeapRegion* remove_head();
tonyp@2472 287
tonyp@2472 288 // Convenience method.
tonyp@2472 289 inline HeapRegion* remove_head_or_null();
tonyp@2472 290
tonyp@2472 291 // It moves the regions from from_list to this list and empties
tonyp@2472 292 // from_list. The new regions will appear in the same order as they
tonyp@2472 293 // were in from_list and be linked in the end of this list.
tonyp@2472 294 void add_as_tail(HeapRegionLinkedList* from_list);
tonyp@2472 295
tonyp@2472 296 // It empties the list by removing all regions from it.
tonyp@2472 297 void remove_all();
tonyp@2472 298
tonyp@2472 299 // It removes all regions in the list that are pending for removal
tonyp@2472 300 // (i.e., they have been tagged with "pending_removal"). The list
tonyp@2472 301 // must not be empty, target_count should reflect the exact number
tonyp@2472 302 // of regions that are pending for removal in the list, and
tonyp@2472 303 // target_count should be > 1 (currently, we never need to remove a
tonyp@2472 304 // single region using this).
tonyp@2472 305 void remove_all_pending(size_t target_count);
tonyp@2472 306
tonyp@2472 307 virtual void verify();
tonyp@2472 308
tonyp@2472 309 virtual void print_on(outputStream* out, bool print_contents = false);
tonyp@2472 310 };
tonyp@2472 311
tonyp@2472 312 //////////////////// HeapRegionLinkedList ////////////////////
tonyp@2472 313
tonyp@2472 314 // Iterator class that provides a convenient way to iterator over the
tonyp@2472 315 // regions in a HeapRegionLinkedList instance.
tonyp@2472 316
tonyp@2472 317 class HeapRegionLinkedListIterator : public StackObj {
tonyp@2472 318 private:
tonyp@2472 319 HeapRegionLinkedList* _list;
tonyp@2472 320 HeapRegion* _curr;
tonyp@2472 321
tonyp@2472 322 public:
tonyp@2472 323 bool more_available() {
tonyp@2472 324 return _curr != NULL;
tonyp@2472 325 }
tonyp@2472 326
tonyp@2472 327 HeapRegion* get_next() {
tonyp@2472 328 assert(more_available(),
tonyp@2472 329 "get_next() should be called when more regions are available");
tonyp@2472 330
tonyp@2472 331 // If we are going to introduce a count in the iterator we should
tonyp@2472 332 // do the "cycle" check.
tonyp@2472 333
tonyp@2472 334 HeapRegion* hr = _curr;
tonyp@2472 335 assert(_list->verify_region(hr, _list), "region verification");
tonyp@2472 336 _curr = hr->next();
tonyp@2472 337 return hr;
tonyp@2472 338 }
tonyp@2472 339
tonyp@2472 340 HeapRegionLinkedListIterator(HeapRegionLinkedList* list)
tonyp@2472 341 : _curr(NULL), _list(list) {
tonyp@2472 342 _curr = list->head();
tonyp@2472 343 }
tonyp@2472 344 };
tonyp@2472 345
tonyp@2472 346 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP

mercurial