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

Mon, 02 Aug 2010 12:51:43 -0700

author
johnc
date
Mon, 02 Aug 2010 12:51:43 -0700
changeset 2060
2d160770d2e5
parent 1907
c18cbe5936b8
child 2239
9f4848ebbabd
permissions
-rw-r--r--

6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 // Sparse remembered set for a heap region (the "owning" region). Maps
ysr@777 26 // indices of other regions to short sequences of cards in the other region
ysr@777 27 // that might contain pointers into the owner region.
ysr@777 28
ysr@777 29 // These tables only expand while they are accessed in parallel --
ysr@777 30 // deletions may be done in single-threaded code. This allows us to allow
ysr@777 31 // unsynchronized reads/iterations, as long as expansions caused by
ysr@777 32 // insertions only enqueue old versions for deletions, but do not delete
ysr@777 33 // old versions synchronously.
ysr@777 34
apetrusenko@984 35 class SparsePRTEntry: public CHeapObj {
ysr@777 36 public:
ysr@777 37 enum SomePublicConstants {
iveresov@1696 38 NullEntry = -1,
iveresov@1696 39 UnrollFactor = 4
ysr@777 40 };
ysr@777 41 private:
johnc@1242 42 RegionIdx_t _region_ind;
johnc@1242 43 int _next_index;
iveresov@1696 44 CardIdx_t _cards[1];
iveresov@1696 45 // WARNING: Don't put any data members beyond this line. Card array has, in fact, variable length.
iveresov@1696 46 // It should always be the last data member.
ysr@777 47 public:
iveresov@1696 48 // Returns the size of the entry, used for entry allocation.
iveresov@1696 49 static size_t size() { return sizeof(SparsePRTEntry) + sizeof(CardIdx_t) * (cards_num() - 1); }
iveresov@1696 50 // Returns the size of the card array.
iveresov@1696 51 static int cards_num() {
iveresov@1696 52 // The number of cards should be a multiple of 4, because that's our current
iveresov@1696 53 // unrolling factor.
iveresov@1696 54 static const int s = MAX2<int>(G1RSetSparseRegionEntries & ~(UnrollFactor - 1), UnrollFactor);
iveresov@1696 55 return s;
iveresov@1696 56 }
ysr@777 57
ysr@777 58 // Set the region_ind to the given value, and delete all cards.
johnc@1242 59 inline void init(RegionIdx_t region_ind);
ysr@777 60
johnc@1242 61 RegionIdx_t r_ind() const { return _region_ind; }
ysr@777 62 bool valid_entry() const { return r_ind() >= 0; }
johnc@1242 63 void set_r_ind(RegionIdx_t rind) { _region_ind = rind; }
ysr@777 64
johnc@1242 65 int next_index() const { return _next_index; }
johnc@1242 66 int* next_index_addr() { return &_next_index; }
johnc@1242 67 void set_next_index(int ni) { _next_index = ni; }
ysr@777 68
ysr@777 69 // Returns "true" iff the entry contains the given card index.
johnc@1242 70 inline bool contains_card(CardIdx_t card_index) const;
ysr@777 71
ysr@777 72 // Returns the number of non-NULL card entries.
ysr@777 73 inline int num_valid_cards() const;
ysr@777 74
ysr@777 75 // Requires that the entry not contain the given card index. If there is
ysr@777 76 // space available, add the given card index to the entry and return
ysr@777 77 // "true"; otherwise, return "false" to indicate that the entry is full.
ysr@777 78 enum AddCardResult {
ysr@777 79 overflow,
ysr@777 80 found,
ysr@777 81 added
ysr@777 82 };
johnc@1242 83 inline AddCardResult add_card(CardIdx_t card_index);
ysr@777 84
ysr@777 85 // Copy the current entry's cards into "cards".
johnc@1242 86 inline void copy_cards(CardIdx_t* cards) const;
ysr@777 87 // Copy the current entry's cards into the "_card" array of "e."
ysr@777 88 inline void copy_cards(SparsePRTEntry* e) const;
ysr@777 89
johnc@1242 90 inline CardIdx_t card(int i) const { return _cards[i]; }
ysr@777 91 };
ysr@777 92
ysr@777 93
ysr@777 94 class RSHashTable : public CHeapObj {
ysr@777 95
ysr@777 96 friend class RSHashTableIter;
ysr@777 97
ysr@777 98 enum SomePrivateConstants {
ysr@777 99 NullEntry = -1
ysr@777 100 };
ysr@777 101
ysr@777 102 size_t _capacity;
ysr@777 103 size_t _capacity_mask;
ysr@777 104 size_t _occupied_entries;
ysr@777 105 size_t _occupied_cards;
ysr@777 106
ysr@777 107 SparsePRTEntry* _entries;
johnc@1242 108 int* _buckets;
johnc@1242 109 int _free_region;
johnc@1242 110 int _free_list;
ysr@777 111
ysr@777 112 // Requires that the caller hold a lock preventing parallel modifying
ysr@777 113 // operations, and that the the table be less than completely full. If
ysr@777 114 // an entry for "region_ind" is already in the table, finds it and
ysr@777 115 // returns its address; otherwise returns "NULL."
johnc@1242 116 SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
ysr@777 117
ysr@777 118 // Requires that the caller hold a lock preventing parallel modifying
ysr@777 119 // operations, and that the the table be less than completely full. If
ysr@777 120 // an entry for "region_ind" is already in the table, finds it and
ysr@777 121 // returns its address; otherwise allocates, initializes, inserts and
ysr@777 122 // returns a new entry for "region_ind".
johnc@1242 123 SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
ysr@777 124
ysr@777 125 // Returns the index of the next free entry in "_entries".
johnc@1242 126 int alloc_entry();
ysr@777 127 // Declares the entry "fi" to be free. (It must have already been
ysr@777 128 // deleted from any bucket lists.
johnc@1242 129 void free_entry(int fi);
ysr@777 130
ysr@777 131 public:
ysr@777 132 RSHashTable(size_t capacity);
ysr@777 133 ~RSHashTable();
ysr@777 134
ysr@777 135 // Attempts to ensure that the given card_index in the given region is in
ysr@777 136 // the sparse table. If successful (because the card was already
ysr@777 137 // present, or because it was successfullly added) returns "true".
ysr@777 138 // Otherwise, returns "false" to indicate that the addition would
ysr@777 139 // overflow the entry for the region. The caller must transfer these
ysr@777 140 // entries to a larger-capacity representation.
johnc@1242 141 bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
ysr@777 142
johnc@1242 143 bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
iveresov@1696 144
johnc@1242 145 bool delete_entry(RegionIdx_t region_id);
ysr@777 146
johnc@1242 147 bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
ysr@777 148
ysr@777 149 void add_entry(SparsePRTEntry* e);
ysr@777 150
iveresov@1696 151 SparsePRTEntry* get_entry(RegionIdx_t region_id);
iveresov@1696 152
ysr@777 153 void clear();
ysr@777 154
ysr@777 155 size_t capacity() const { return _capacity; }
ysr@777 156 size_t capacity_mask() const { return _capacity_mask; }
ysr@777 157 size_t occupied_entries() const { return _occupied_entries; }
ysr@777 158 size_t occupied_cards() const { return _occupied_cards; }
ysr@777 159 size_t mem_size() const;
ysr@777 160
iveresov@1696 161 SparsePRTEntry* entry(int i) const { return (SparsePRTEntry*)((char*)_entries + SparsePRTEntry::size() * i); }
ysr@777 162
ysr@777 163 void print();
ysr@777 164 };
ysr@777 165
johnc@1242 166 // ValueObj because will be embedded in HRRS iterator.
apetrusenko@984 167 class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
johnc@1242 168 int _tbl_ind; // [-1, 0.._rsht->_capacity)
johnc@1242 169 int _bl_ind; // [-1, 0.._rsht->_capacity)
iveresov@1696 170 short _card_ind; // [0..SparsePRTEntry::cards_num())
johnc@1242 171 RSHashTable* _rsht;
johnc@1242 172 size_t _heap_bot_card_ind;
ysr@777 173
johnc@1242 174 // If the bucket list pointed to by _bl_ind contains a card, sets
johnc@1242 175 // _bl_ind to the index of that entry, and returns the card.
johnc@1242 176 // Otherwise, returns SparseEntry::NullEntry.
johnc@1242 177 CardIdx_t find_first_card_in_list();
ysr@777 178
johnc@1242 179 // Computes the proper card index for the card whose offset in the
johnc@1242 180 // current region (as indicated by _bl_ind) is "ci".
johnc@1242 181 // This is subject to errors when there is iteration concurrent with
johnc@1242 182 // modification, but these errors should be benign.
johnc@1242 183 size_t compute_card_ind(CardIdx_t ci);
ysr@777 184
johnc@1242 185 public:
johnc@1242 186 RSHashTableIter(size_t heap_bot_card_ind) :
johnc@1242 187 _tbl_ind(RSHashTable::NullEntry),
johnc@1242 188 _bl_ind(RSHashTable::NullEntry),
iveresov@1696 189 _card_ind((SparsePRTEntry::cards_num() - 1)),
johnc@1242 190 _rsht(NULL),
johnc@1242 191 _heap_bot_card_ind(heap_bot_card_ind)
johnc@1242 192 {}
ysr@777 193
johnc@1242 194 void init(RSHashTable* rsht) {
johnc@1242 195 _rsht = rsht;
johnc@1242 196 _tbl_ind = -1; // So that first increment gets to 0.
johnc@1242 197 _bl_ind = RSHashTable::NullEntry;
iveresov@1696 198 _card_ind = (SparsePRTEntry::cards_num() - 1);
johnc@1242 199 }
ysr@777 200
johnc@1242 201 bool has_next(size_t& card_index);
johnc@1242 202 };
ysr@777 203
ysr@777 204 // Concurrent accesss to a SparsePRT must be serialized by some external
ysr@777 205 // mutex.
ysr@777 206
ysr@777 207 class SparsePRTIter;
ysr@777 208
apetrusenko@984 209 class SparsePRT VALUE_OBJ_CLASS_SPEC {
ysr@777 210 // Iterations are done on the _cur hash table, since they only need to
ysr@777 211 // see entries visible at the start of a collection pause.
ysr@777 212 // All other operations are done using the _next hash table.
ysr@777 213 RSHashTable* _cur;
ysr@777 214 RSHashTable* _next;
ysr@777 215
ysr@777 216 HeapRegion* _hr;
ysr@777 217
ysr@777 218 enum SomeAdditionalPrivateConstants {
ysr@777 219 InitialCapacity = 16
ysr@777 220 };
ysr@777 221
ysr@777 222 void expand();
ysr@777 223
ysr@777 224 bool _expanded;
ysr@777 225
ysr@777 226 bool expanded() { return _expanded; }
ysr@777 227 void set_expanded(bool b) { _expanded = b; }
ysr@777 228
ysr@777 229 SparsePRT* _next_expanded;
ysr@777 230
ysr@777 231 SparsePRT* next_expanded() { return _next_expanded; }
ysr@777 232 void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }
ysr@777 233
ysr@777 234 static SparsePRT* _head_expanded_list;
ysr@777 235
ysr@777 236 public:
ysr@777 237 SparsePRT(HeapRegion* hr);
ysr@777 238
ysr@777 239 ~SparsePRT();
ysr@777 240
ysr@777 241 size_t occupied() const { return _next->occupied_cards(); }
ysr@777 242 size_t mem_size() const;
ysr@777 243
ysr@777 244 // Attempts to ensure that the given card_index in the given region is in
ysr@777 245 // the sparse table. If successful (because the card was already
ysr@777 246 // present, or because it was successfullly added) returns "true".
ysr@777 247 // Otherwise, returns "false" to indicate that the addition would
ysr@777 248 // overflow the entry for the region. The caller must transfer these
ysr@777 249 // entries to a larger-capacity representation.
johnc@1242 250 bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
ysr@777 251
ysr@777 252 // If the table hold an entry for "region_ind", Copies its
ysr@777 253 // cards into "cards", which must be an array of length at least
iveresov@1696 254 // "SparePRTEntry::cards_num()", and returns "true"; otherwise,
iveresov@1696 255 // returns "false".
johnc@1242 256 bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
ysr@777 257
iveresov@1696 258 // Return the pointer to the entry associated with the given region.
iveresov@1696 259 SparsePRTEntry* get_entry(RegionIdx_t region_ind);
iveresov@1696 260
ysr@777 261 // If there is an entry for "region_ind", removes it and return "true";
ysr@777 262 // otherwise returns "false."
johnc@1242 263 bool delete_entry(RegionIdx_t region_ind);
ysr@777 264
ysr@777 265 // Clear the table, and reinitialize to initial capacity.
ysr@777 266 void clear();
ysr@777 267
ysr@777 268 // Ensure that "_cur" and "_next" point to the same table.
ysr@777 269 void cleanup();
ysr@777 270
ysr@777 271 // Clean up all tables on the expanded list. Called single threaded.
ysr@777 272 static void cleanup_all();
tonyp@1052 273 RSHashTable* cur() const { return _cur; }
ysr@777 274
ysr@777 275 void init_iterator(SparsePRTIter* sprt_iter);
ysr@777 276
ysr@777 277 static void add_to_expanded_list(SparsePRT* sprt);
ysr@777 278 static SparsePRT* get_from_expanded_list();
ysr@777 279
johnc@1242 280 bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
ysr@777 281 return _next->contains_card(region_id, card_index);
ysr@777 282 }
ysr@777 283
ysr@777 284 #if 0
ysr@777 285 void verify_is_cleared();
ysr@777 286 void print();
ysr@777 287 #endif
ysr@777 288 };
ysr@777 289
ysr@777 290
ysr@777 291 class SparsePRTIter: public /* RSHashTable:: */RSHashTableIter {
ysr@777 292 public:
ysr@777 293 SparsePRTIter(size_t heap_bot_card_ind) :
ysr@777 294 /* RSHashTable:: */RSHashTableIter(heap_bot_card_ind)
ysr@777 295 {}
ysr@777 296
ysr@777 297 void init(const SparsePRT* sprt) {
tonyp@1052 298 RSHashTableIter::init(sprt->cur());
ysr@777 299 }
ysr@777 300 bool has_next(size_t& card_index) {
ysr@777 301 return RSHashTableIter::has_next(card_index);
ysr@777 302 }
ysr@777 303 };

mercurial