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

Fri, 04 Apr 2014 10:43:56 +0200

author
tschatzl
date
Fri, 04 Apr 2014 10:43:56 +0200
changeset 6541
bfdf528be8e8
parent 6198
55fb97c4c58d
child 6876
710a3c8b516e
permissions
-rw-r--r--

8038498: Fix includes and C inlining after 8035330
Summary: Change 8035330: Remove G1ParScanPartialArrayClosure and G1ParScanHeapEvacClosure broke the debug build on AIX. The method do_oop_partial_array() is added in a header, but requires the inline function par_write_ref() through several inlined calls. In some cpp files, like arguments.cpp, par_write_ref() is not defined as the corresponding inline header and is not included. The AIX debug VM does not start because of the missing symbol. This change solves this by cleaning up include dependencies.
Reviewed-by: tschatzl, stefank

ysr@777 1 /*
mikael@6198 2 * Copyright (c) 2001, 2013, 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
stefank@2314 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
stefank@2314 27
tschatzl@6541 28 #include "gc_implementation/g1/g1CollectedHeap.hpp"
stefank@2314 29 #include "gc_implementation/g1/heapRegion.hpp"
stefank@2314 30 #include "memory/allocation.hpp"
stefank@2314 31 #include "memory/cardTableModRefBS.hpp"
stefank@2314 32 #include "runtime/mutex.hpp"
stefank@2314 33 #include "utilities/globalDefinitions.hpp"
stefank@2314 34
ysr@777 35 // Sparse remembered set for a heap region (the "owning" region). Maps
ysr@777 36 // indices of other regions to short sequences of cards in the other region
ysr@777 37 // that might contain pointers into the owner region.
ysr@777 38
ysr@777 39 // These tables only expand while they are accessed in parallel --
ysr@777 40 // deletions may be done in single-threaded code. This allows us to allow
ysr@777 41 // unsynchronized reads/iterations, as long as expansions caused by
ysr@777 42 // insertions only enqueue old versions for deletions, but do not delete
ysr@777 43 // old versions synchronously.
ysr@777 44
zgu@3900 45 class SparsePRTEntry: public CHeapObj<mtGC> {
ysr@777 46 public:
ysr@777 47 enum SomePublicConstants {
iveresov@1696 48 NullEntry = -1,
iveresov@1696 49 UnrollFactor = 4
ysr@777 50 };
ysr@777 51 private:
johnc@1242 52 RegionIdx_t _region_ind;
johnc@1242 53 int _next_index;
iveresov@1696 54 CardIdx_t _cards[1];
iveresov@1696 55 // WARNING: Don't put any data members beyond this line. Card array has, in fact, variable length.
iveresov@1696 56 // It should always be the last data member.
ysr@777 57 public:
iveresov@1696 58 // Returns the size of the entry, used for entry allocation.
iveresov@1696 59 static size_t size() { return sizeof(SparsePRTEntry) + sizeof(CardIdx_t) * (cards_num() - 1); }
iveresov@1696 60 // Returns the size of the card array.
iveresov@1696 61 static int cards_num() {
iveresov@1696 62 // The number of cards should be a multiple of 4, because that's our current
iveresov@1696 63 // unrolling factor.
iveresov@1696 64 static const int s = MAX2<int>(G1RSetSparseRegionEntries & ~(UnrollFactor - 1), UnrollFactor);
iveresov@1696 65 return s;
iveresov@1696 66 }
ysr@777 67
ysr@777 68 // Set the region_ind to the given value, and delete all cards.
johnc@1242 69 inline void init(RegionIdx_t region_ind);
ysr@777 70
johnc@1242 71 RegionIdx_t r_ind() const { return _region_ind; }
ysr@777 72 bool valid_entry() const { return r_ind() >= 0; }
johnc@1242 73 void set_r_ind(RegionIdx_t rind) { _region_ind = rind; }
ysr@777 74
johnc@1242 75 int next_index() const { return _next_index; }
johnc@1242 76 int* next_index_addr() { return &_next_index; }
johnc@1242 77 void set_next_index(int ni) { _next_index = ni; }
ysr@777 78
ysr@777 79 // Returns "true" iff the entry contains the given card index.
johnc@1242 80 inline bool contains_card(CardIdx_t card_index) const;
ysr@777 81
ysr@777 82 // Returns the number of non-NULL card entries.
ysr@777 83 inline int num_valid_cards() const;
ysr@777 84
ysr@777 85 // Requires that the entry not contain the given card index. If there is
ysr@777 86 // space available, add the given card index to the entry and return
ysr@777 87 // "true"; otherwise, return "false" to indicate that the entry is full.
ysr@777 88 enum AddCardResult {
ysr@777 89 overflow,
ysr@777 90 found,
ysr@777 91 added
ysr@777 92 };
johnc@1242 93 inline AddCardResult add_card(CardIdx_t card_index);
ysr@777 94
ysr@777 95 // Copy the current entry's cards into "cards".
johnc@1242 96 inline void copy_cards(CardIdx_t* cards) const;
ysr@777 97 // Copy the current entry's cards into the "_card" array of "e."
ysr@777 98 inline void copy_cards(SparsePRTEntry* e) const;
ysr@777 99
johnc@1242 100 inline CardIdx_t card(int i) const { return _cards[i]; }
ysr@777 101 };
ysr@777 102
ysr@777 103
zgu@3900 104 class RSHashTable : public CHeapObj<mtGC> {
ysr@777 105
ysr@777 106 friend class RSHashTableIter;
ysr@777 107
ysr@777 108 enum SomePrivateConstants {
ysr@777 109 NullEntry = -1
ysr@777 110 };
ysr@777 111
ysr@777 112 size_t _capacity;
ysr@777 113 size_t _capacity_mask;
ysr@777 114 size_t _occupied_entries;
ysr@777 115 size_t _occupied_cards;
ysr@777 116
ysr@777 117 SparsePRTEntry* _entries;
johnc@1242 118 int* _buckets;
johnc@1242 119 int _free_region;
johnc@1242 120 int _free_list;
ysr@777 121
ysr@777 122 // Requires that the caller hold a lock preventing parallel modifying
ysr@777 123 // operations, and that the the table be less than completely full. If
ysr@777 124 // an entry for "region_ind" is already in the table, finds it and
ysr@777 125 // returns its address; otherwise returns "NULL."
johnc@1242 126 SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
ysr@777 127
ysr@777 128 // Requires that the caller hold a lock preventing parallel modifying
ysr@777 129 // operations, and that the the table be less than completely full. If
ysr@777 130 // an entry for "region_ind" is already in the table, finds it and
ysr@777 131 // returns its address; otherwise allocates, initializes, inserts and
ysr@777 132 // returns a new entry for "region_ind".
johnc@1242 133 SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
ysr@777 134
ysr@777 135 // Returns the index of the next free entry in "_entries".
johnc@1242 136 int alloc_entry();
ysr@777 137 // Declares the entry "fi" to be free. (It must have already been
ysr@777 138 // deleted from any bucket lists.
johnc@1242 139 void free_entry(int fi);
ysr@777 140
ysr@777 141 public:
ysr@777 142 RSHashTable(size_t capacity);
ysr@777 143 ~RSHashTable();
ysr@777 144
ysr@777 145 // Attempts to ensure that the given card_index in the given region is in
ysr@777 146 // the sparse table. If successful (because the card was already
ysr@777 147 // present, or because it was successfullly added) returns "true".
ysr@777 148 // Otherwise, returns "false" to indicate that the addition would
ysr@777 149 // overflow the entry for the region. The caller must transfer these
ysr@777 150 // entries to a larger-capacity representation.
johnc@1242 151 bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
ysr@777 152
johnc@1242 153 bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
iveresov@1696 154
johnc@1242 155 bool delete_entry(RegionIdx_t region_id);
ysr@777 156
johnc@1242 157 bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
ysr@777 158
ysr@777 159 void add_entry(SparsePRTEntry* e);
ysr@777 160
iveresov@1696 161 SparsePRTEntry* get_entry(RegionIdx_t region_id);
iveresov@1696 162
ysr@777 163 void clear();
ysr@777 164
ysr@777 165 size_t capacity() const { return _capacity; }
ysr@777 166 size_t capacity_mask() const { return _capacity_mask; }
ysr@777 167 size_t occupied_entries() const { return _occupied_entries; }
ysr@777 168 size_t occupied_cards() const { return _occupied_cards; }
ysr@777 169 size_t mem_size() const;
ysr@777 170
iveresov@1696 171 SparsePRTEntry* entry(int i) const { return (SparsePRTEntry*)((char*)_entries + SparsePRTEntry::size() * i); }
ysr@777 172
ysr@777 173 void print();
ysr@777 174 };
ysr@777 175
johnc@1242 176 // ValueObj because will be embedded in HRRS iterator.
apetrusenko@984 177 class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
johnc@1242 178 int _tbl_ind; // [-1, 0.._rsht->_capacity)
johnc@1242 179 int _bl_ind; // [-1, 0.._rsht->_capacity)
iveresov@1696 180 short _card_ind; // [0..SparsePRTEntry::cards_num())
johnc@1242 181 RSHashTable* _rsht;
ysr@777 182
johnc@1242 183 // If the bucket list pointed to by _bl_ind contains a card, sets
johnc@1242 184 // _bl_ind to the index of that entry, and returns the card.
johnc@1242 185 // Otherwise, returns SparseEntry::NullEntry.
johnc@1242 186 CardIdx_t find_first_card_in_list();
ysr@777 187
johnc@1242 188 // Computes the proper card index for the card whose offset in the
johnc@1242 189 // current region (as indicated by _bl_ind) is "ci".
johnc@1242 190 // This is subject to errors when there is iteration concurrent with
johnc@1242 191 // modification, but these errors should be benign.
johnc@1242 192 size_t compute_card_ind(CardIdx_t ci);
ysr@777 193
johnc@1242 194 public:
johnc@5014 195 RSHashTableIter(RSHashTable* rsht) :
johnc@5014 196 _tbl_ind(RSHashTable::NullEntry), // So that first increment gets to 0.
johnc@1242 197 _bl_ind(RSHashTable::NullEntry),
iveresov@1696 198 _card_ind((SparsePRTEntry::cards_num() - 1)),
johnc@5014 199 _rsht(rsht) {}
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;
tonyp@2493 208 class SparsePRTCleanupTask;
ysr@777 209
apetrusenko@984 210 class SparsePRT VALUE_OBJ_CLASS_SPEC {
tonyp@2493 211 friend class SparsePRTCleanupTask;
tonyp@2493 212
ysr@777 213 // Iterations are done on the _cur hash table, since they only need to
ysr@777 214 // see entries visible at the start of a collection pause.
ysr@777 215 // All other operations are done using the _next hash table.
ysr@777 216 RSHashTable* _cur;
ysr@777 217 RSHashTable* _next;
ysr@777 218
ysr@777 219 HeapRegion* _hr;
ysr@777 220
ysr@777 221 enum SomeAdditionalPrivateConstants {
ysr@777 222 InitialCapacity = 16
ysr@777 223 };
ysr@777 224
ysr@777 225 void expand();
ysr@777 226
ysr@777 227 bool _expanded;
ysr@777 228
ysr@777 229 bool expanded() { return _expanded; }
ysr@777 230 void set_expanded(bool b) { _expanded = b; }
ysr@777 231
ysr@777 232 SparsePRT* _next_expanded;
ysr@777 233
ysr@777 234 SparsePRT* next_expanded() { return _next_expanded; }
ysr@777 235 void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }
ysr@777 236
tonyp@2493 237 bool should_be_on_expanded_list();
tonyp@2493 238
ysr@777 239 static SparsePRT* _head_expanded_list;
ysr@777 240
ysr@777 241 public:
ysr@777 242 SparsePRT(HeapRegion* hr);
ysr@777 243
ysr@777 244 ~SparsePRT();
ysr@777 245
ysr@777 246 size_t occupied() const { return _next->occupied_cards(); }
ysr@777 247 size_t mem_size() const;
ysr@777 248
ysr@777 249 // Attempts to ensure that the given card_index in the given region is in
ysr@777 250 // the sparse table. If successful (because the card was already
ysr@777 251 // present, or because it was successfullly added) returns "true".
ysr@777 252 // Otherwise, returns "false" to indicate that the addition would
ysr@777 253 // overflow the entry for the region. The caller must transfer these
ysr@777 254 // entries to a larger-capacity representation.
johnc@1242 255 bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
ysr@777 256
ysr@777 257 // If the table hold an entry for "region_ind", Copies its
ysr@777 258 // cards into "cards", which must be an array of length at least
iveresov@1696 259 // "SparePRTEntry::cards_num()", and returns "true"; otherwise,
iveresov@1696 260 // returns "false".
johnc@1242 261 bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
ysr@777 262
iveresov@1696 263 // Return the pointer to the entry associated with the given region.
iveresov@1696 264 SparsePRTEntry* get_entry(RegionIdx_t region_ind);
iveresov@1696 265
ysr@777 266 // If there is an entry for "region_ind", removes it and return "true";
ysr@777 267 // otherwise returns "false."
johnc@1242 268 bool delete_entry(RegionIdx_t region_ind);
ysr@777 269
ysr@777 270 // Clear the table, and reinitialize to initial capacity.
ysr@777 271 void clear();
ysr@777 272
ysr@777 273 // Ensure that "_cur" and "_next" point to the same table.
ysr@777 274 void cleanup();
ysr@777 275
ysr@777 276 // Clean up all tables on the expanded list. Called single threaded.
ysr@777 277 static void cleanup_all();
tonyp@1052 278 RSHashTable* cur() const { return _cur; }
ysr@777 279
ysr@777 280 static void add_to_expanded_list(SparsePRT* sprt);
ysr@777 281 static SparsePRT* get_from_expanded_list();
ysr@777 282
tonyp@2493 283 // The purpose of these three methods is to help the GC workers
tonyp@2493 284 // during the cleanup pause to recreate the expanded list, purging
tonyp@2493 285 // any tables from it that belong to regions that are freed during
tonyp@2493 286 // cleanup (if we don't purge those tables, there is a race that
tonyp@2493 287 // causes various crashes; see CR 7014261).
tonyp@2493 288 //
tonyp@2493 289 // We chose to recreate the expanded list, instead of purging
tonyp@2493 290 // entries from it by iterating over it, to avoid this serial phase
tonyp@2493 291 // at the end of the cleanup pause.
tonyp@2493 292 //
tonyp@2493 293 // The three methods below work as follows:
tonyp@2493 294 // * reset_for_cleanup_tasks() : Nulls the expanded list head at the
tonyp@2493 295 // start of the cleanup pause.
tonyp@2493 296 // * do_cleanup_work() : Called by the cleanup workers for every
tonyp@2493 297 // region that is not free / is being freed by the cleanup
tonyp@2493 298 // pause. It creates a list of expanded tables whose head / tail
tonyp@2493 299 // are on the thread-local SparsePRTCleanupTask object.
tonyp@2493 300 // * finish_cleanup_task() : Called by the cleanup workers after
tonyp@2493 301 // they complete their cleanup task. It adds the local list into
tonyp@2493 302 // the global expanded list. It assumes that the
tonyp@2493 303 // ParGCRareEvent_lock is being held to ensure MT-safety.
tonyp@2493 304 static void reset_for_cleanup_tasks();
tonyp@2493 305 void do_cleanup_work(SparsePRTCleanupTask* sprt_cleanup_task);
tonyp@2493 306 static void finish_cleanup_task(SparsePRTCleanupTask* sprt_cleanup_task);
tonyp@2493 307
johnc@1242 308 bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
ysr@777 309 return _next->contains_card(region_id, card_index);
ysr@777 310 }
ysr@777 311 };
ysr@777 312
tonyp@2239 313 class SparsePRTIter: public RSHashTableIter {
ysr@777 314 public:
johnc@5014 315 SparsePRTIter(const SparsePRT* sprt) :
johnc@5014 316 RSHashTableIter(sprt->cur()) {}
johnc@5014 317
ysr@777 318 bool has_next(size_t& card_index) {
ysr@777 319 return RSHashTableIter::has_next(card_index);
ysr@777 320 }
ysr@777 321 };
stefank@2314 322
tonyp@2493 323 // This allows each worker during a cleanup pause to create a
tonyp@2493 324 // thread-local list of sparse tables that have been expanded and need
tonyp@2493 325 // to be processed at the beginning of the next GC pause. This lists
tonyp@2493 326 // are concatenated into the single expanded list at the end of the
tonyp@2493 327 // cleanup pause.
tonyp@2493 328 class SparsePRTCleanupTask VALUE_OBJ_CLASS_SPEC {
tonyp@2493 329 private:
tonyp@2493 330 SparsePRT* _head;
tonyp@2493 331 SparsePRT* _tail;
tonyp@2493 332
tonyp@2493 333 public:
tonyp@2493 334 SparsePRTCleanupTask() : _head(NULL), _tail(NULL) { }
tonyp@2493 335
tonyp@2493 336 void add(SparsePRT* sprt);
tonyp@2493 337 SparsePRT* head() { return _head; }
tonyp@2493 338 SparsePRT* tail() { return _tail; }
tonyp@2493 339 };
tonyp@2493 340
stefank@2314 341 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP

mercurial