sparsePRT.hpp 10.2 KB
Newer Older
1
/*
X
xdono 已提交
2
 * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

// Sparse remembered set for a heap region (the "owning" region).  Maps
// indices of other regions to short sequences of cards in the other region
// that might contain pointers into the owner region.

// These tables only expand while they are accessed in parallel --
// deletions may be done in single-threaded code.  This allows us to allow
// unsynchronized reads/iterations, as long as expansions caused by
// insertions only enqueue old versions for deletions, but do not delete
// old versions synchronously.

35
class SparsePRTEntry: public CHeapObj {
36 37
public:
  enum SomePublicConstants {
38 39
    NullEntry     = -1,
    UnrollFactor  =  4
40 41
  };
private:
42 43
  RegionIdx_t _region_ind;
  int         _next_index;
44 45 46
  CardIdx_t   _cards[1];
  // WARNING: Don't put any data members beyond this line. Card array has, in fact, variable length.
  // It should always be the last data member.
47
public:
48 49 50 51 52 53 54 55 56
  // Returns the size of the entry, used for entry allocation.
  static size_t size() { return sizeof(SparsePRTEntry) + sizeof(CardIdx_t) * (cards_num() - 1); }
  // Returns the size of the card array.
  static int cards_num() {
    // The number of cards should be a multiple of 4, because that's our current
    // unrolling factor.
    static const int s = MAX2<int>(G1RSetSparseRegionEntries & ~(UnrollFactor - 1), UnrollFactor);
    return s;
  }
57 58

  // Set the region_ind to the given value, and delete all cards.
59
  inline void init(RegionIdx_t region_ind);
60

61
  RegionIdx_t r_ind() const { return _region_ind; }
62
  bool valid_entry() const { return r_ind() >= 0; }
63
  void set_r_ind(RegionIdx_t rind) { _region_ind = rind; }
64

65 66 67
  int next_index() const { return _next_index; }
  int* next_index_addr() { return &_next_index; }
  void set_next_index(int ni) { _next_index = ni; }
68 69

  // Returns "true" iff the entry contains the given card index.
70
  inline bool contains_card(CardIdx_t card_index) const;
71 72 73 74 75 76 77 78 79 80 81 82

  // Returns the number of non-NULL card entries.
  inline int num_valid_cards() const;

  // Requires that the entry not contain the given card index.  If there is
  // space available, add the given card index to the entry and return
  // "true"; otherwise, return "false" to indicate that the entry is full.
  enum AddCardResult {
    overflow,
    found,
    added
  };
83
  inline AddCardResult add_card(CardIdx_t card_index);
84 85

  // Copy the current entry's cards into "cards".
86
  inline void copy_cards(CardIdx_t* cards) const;
87 88 89
  // Copy the current entry's cards into the "_card" array of "e."
  inline void copy_cards(SparsePRTEntry* e) const;

90
  inline CardIdx_t card(int i) const { return _cards[i]; }
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
};


class RSHashTable : public CHeapObj {

  friend class RSHashTableIter;

  enum SomePrivateConstants {
    NullEntry = -1
  };

  size_t _capacity;
  size_t _capacity_mask;
  size_t _occupied_entries;
  size_t _occupied_cards;

  SparsePRTEntry* _entries;
108 109 110
  int* _buckets;
  int  _free_region;
  int  _free_list;
111 112 113 114 115

  // Requires that the caller hold a lock preventing parallel modifying
  // operations, and that the the table be less than completely full.  If
  // an entry for "region_ind" is already in the table, finds it and
  // returns its address; otherwise returns "NULL."
116
  SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
117 118 119 120 121 122

  // Requires that the caller hold a lock preventing parallel modifying
  // operations, and that the the table be less than completely full.  If
  // an entry for "region_ind" is already in the table, finds it and
  // returns its address; otherwise allocates, initializes, inserts and
  // returns a new entry for "region_ind".
123
  SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
124 125

  // Returns the index of the next free entry in "_entries".
126
  int alloc_entry();
127 128
  // Declares the entry "fi" to be free.  (It must have already been
  // deleted from any bucket lists.
129
  void free_entry(int fi);
130 131 132 133 134 135 136 137 138 139 140

public:
  RSHashTable(size_t capacity);
  ~RSHashTable();

  // Attempts to ensure that the given card_index in the given region is in
  // the sparse table.  If successful (because the card was already
  // present, or because it was successfullly added) returns "true".
  // Otherwise, returns "false" to indicate that the addition would
  // overflow the entry for the region.  The caller must transfer these
  // entries to a larger-capacity representation.
141
  bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
142

143
  bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
144

145
  bool delete_entry(RegionIdx_t region_id);
146

147
  bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
148 149 150

  void add_entry(SparsePRTEntry* e);

151 152
  SparsePRTEntry* get_entry(RegionIdx_t region_id);

153 154 155 156 157 158 159 160
  void clear();

  size_t capacity() const      { return _capacity;       }
  size_t capacity_mask() const { return _capacity_mask;  }
  size_t occupied_entries() const { return _occupied_entries; }
  size_t occupied_cards() const   { return _occupied_cards;   }
  size_t mem_size() const;

161
  SparsePRTEntry* entry(int i) const { return (SparsePRTEntry*)((char*)_entries + SparsePRTEntry::size() * i); }
162 163 164 165

  void print();
};

166
// ValueObj because will be embedded in HRRS iterator.
167
class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
168 169
  int _tbl_ind;         // [-1, 0.._rsht->_capacity)
  int _bl_ind;          // [-1, 0.._rsht->_capacity)
170
  short _card_ind;      // [0..SparsePRTEntry::cards_num())
171 172
  RSHashTable* _rsht;
  size_t _heap_bot_card_ind;
173

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
  // If the bucket list pointed to by _bl_ind contains a card, sets
  // _bl_ind to the index of that entry, and returns the card.
  // Otherwise, returns SparseEntry::NullEntry.
  CardIdx_t find_first_card_in_list();

  // Computes the proper card index for the card whose offset in the
  // current region (as indicated by _bl_ind) is "ci".
  // This is subject to errors when there is iteration concurrent with
  // modification, but these errors should be benign.
  size_t compute_card_ind(CardIdx_t ci);

public:
  RSHashTableIter(size_t heap_bot_card_ind) :
    _tbl_ind(RSHashTable::NullEntry),
    _bl_ind(RSHashTable::NullEntry),
189
    _card_ind((SparsePRTEntry::cards_num() - 1)),
190 191 192 193 194 195 196 197
    _rsht(NULL),
    _heap_bot_card_ind(heap_bot_card_ind)
  {}

  void init(RSHashTable* rsht) {
    _rsht = rsht;
    _tbl_ind = -1; // So that first increment gets to 0.
    _bl_ind = RSHashTable::NullEntry;
198
    _card_ind = (SparsePRTEntry::cards_num() - 1);
199 200 201 202 203
  }

  bool has_next(size_t& card_index);
};

204 205 206 207 208
// Concurrent accesss to a SparsePRT must be serialized by some external
// mutex.

class SparsePRTIter;

209
class SparsePRT VALUE_OBJ_CLASS_SPEC {
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
  //  Iterations are done on the _cur hash table, since they only need to
  //  see entries visible at the start of a collection pause.
  //  All other operations are done using the _next hash table.
  RSHashTable* _cur;
  RSHashTable* _next;

  HeapRegion* _hr;

  enum SomeAdditionalPrivateConstants {
    InitialCapacity = 16
  };

  void expand();

  bool _expanded;

  bool expanded() { return _expanded; }
  void set_expanded(bool b) { _expanded = b; }

  SparsePRT* _next_expanded;

  SparsePRT* next_expanded() { return _next_expanded; }
  void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }

  static SparsePRT* _head_expanded_list;

public:
  SparsePRT(HeapRegion* hr);

  ~SparsePRT();

  size_t occupied() const { return _next->occupied_cards(); }
  size_t mem_size() const;

  // Attempts to ensure that the given card_index in the given region is in
  // the sparse table.  If successful (because the card was already
  // present, or because it was successfullly added) returns "true".
  // Otherwise, returns "false" to indicate that the addition would
  // overflow the entry for the region.  The caller must transfer these
  // entries to a larger-capacity representation.
250
  bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
251 252 253

  // If the table hold an entry for "region_ind",  Copies its
  // cards into "cards", which must be an array of length at least
254 255
  // "SparePRTEntry::cards_num()", and returns "true"; otherwise,
  // returns "false".
256
  bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
257

258 259 260
  // Return the pointer to the entry associated with the given region.
  SparsePRTEntry* get_entry(RegionIdx_t region_ind);

261 262
  // If there is an entry for "region_ind", removes it and return "true";
  // otherwise returns "false."
263
  bool delete_entry(RegionIdx_t region_ind);
264 265 266 267 268 269 270 271 272

  // Clear the table, and reinitialize to initial capacity.
  void clear();

  // Ensure that "_cur" and "_next" point to the same table.
  void cleanup();

  // Clean up all tables on the expanded list.  Called single threaded.
  static void cleanup_all();
273
  RSHashTable* cur() const { return _cur; }
274 275 276 277 278 279

  void init_iterator(SparsePRTIter* sprt_iter);

  static void add_to_expanded_list(SparsePRT* sprt);
  static SparsePRT* get_from_expanded_list();

280
  bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
    return _next->contains_card(region_id, card_index);
  }

#if 0
  void verify_is_cleared();
  void print();
#endif
};


class SparsePRTIter: public /* RSHashTable:: */RSHashTableIter {
public:
  SparsePRTIter(size_t heap_bot_card_ind) :
    /* RSHashTable:: */RSHashTableIter(heap_bot_card_ind)
  {}

  void init(const SparsePRT* sprt) {
298
    RSHashTableIter::init(sprt->cur());
299 300 301 302 303
  }
  bool has_next(size_t& card_index) {
    return RSHashTableIter::has_next(card_index);
  }
};