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

Thu, 11 Jun 2009 17:19:33 -0700

author
johnc
date
Thu, 11 Jun 2009 17:19:33 -0700
changeset 1242
d44bdab1c03d
parent 1063
7bb995fbd3c0
child 1377
2c79770d1f6e
permissions
-rw-r--r--

6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
Summary: For heaps larger than 32Gb, the number of heap regions overflows the data type used to hold the region index in the SparsePRT structure. Changed the region indexes, card indexes, and RSet hash table buckets to ints and added some size overflow guarantees.
Reviewed-by: ysr, tonyp

     1 /*
     2  * Copyright 2001-2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 // Sparse remembered set for a heap region (the "owning" region).  Maps
    26 // indices of other regions to short sequences of cards in the other region
    27 // that might contain pointers into the owner region.
    29 // These tables only expand while they are accessed in parallel --
    30 // deletions may be done in single-threaded code.  This allows us to allow
    31 // unsynchronized reads/iterations, as long as expansions caused by
    32 // insertions only enqueue old versions for deletions, but do not delete
    33 // old versions synchronously.
    36 class SparsePRTEntry: public CHeapObj {
    37 public:
    39   enum SomePublicConstants {
    40     CardsPerEntry =  4,
    41     NullEntry     = -1
    42   };
    44 private:
    45   RegionIdx_t _region_ind;
    46   int         _next_index;
    47   CardIdx_t   _cards[CardsPerEntry];
    49 public:
    51   // Set the region_ind to the given value, and delete all cards.
    52   inline void init(RegionIdx_t region_ind);
    54   RegionIdx_t r_ind() const { return _region_ind; }
    55   bool valid_entry() const { return r_ind() >= 0; }
    56   void set_r_ind(RegionIdx_t rind) { _region_ind = rind; }
    58   int next_index() const { return _next_index; }
    59   int* next_index_addr() { return &_next_index; }
    60   void set_next_index(int ni) { _next_index = ni; }
    62   // Returns "true" iff the entry contains the given card index.
    63   inline bool contains_card(CardIdx_t card_index) const;
    65   // Returns the number of non-NULL card entries.
    66   inline int num_valid_cards() const;
    68   // Requires that the entry not contain the given card index.  If there is
    69   // space available, add the given card index to the entry and return
    70   // "true"; otherwise, return "false" to indicate that the entry is full.
    71   enum AddCardResult {
    72     overflow,
    73     found,
    74     added
    75   };
    76   inline AddCardResult add_card(CardIdx_t card_index);
    78   // Copy the current entry's cards into "cards".
    79   inline void copy_cards(CardIdx_t* cards) const;
    80   // Copy the current entry's cards into the "_card" array of "e."
    81   inline void copy_cards(SparsePRTEntry* e) const;
    83   inline CardIdx_t card(int i) const { return _cards[i]; }
    84 };
    87 class RSHashTable : public CHeapObj {
    89   friend class RSHashTableIter;
    91   enum SomePrivateConstants {
    92     NullEntry = -1
    93   };
    95   size_t _capacity;
    96   size_t _capacity_mask;
    97   size_t _occupied_entries;
    98   size_t _occupied_cards;
   100   SparsePRTEntry* _entries;
   101   int* _buckets;
   102   int  _free_region;
   103   int  _free_list;
   105   static RSHashTable* _head_deleted_list;
   106   RSHashTable* _next_deleted;
   107   RSHashTable* next_deleted() { return _next_deleted; }
   108   void set_next_deleted(RSHashTable* rsht) { _next_deleted = rsht; }
   109   bool _deleted;
   110   void set_deleted(bool b) { _deleted = b; }
   112   // Requires that the caller hold a lock preventing parallel modifying
   113   // operations, and that the the table be less than completely full.  If
   114   // an entry for "region_ind" is already in the table, finds it and
   115   // returns its address; otherwise returns "NULL."
   116   SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
   118   // Requires that the caller hold a lock preventing parallel modifying
   119   // operations, and that the the table be less than completely full.  If
   120   // an entry for "region_ind" is already in the table, finds it and
   121   // returns its address; otherwise allocates, initializes, inserts and
   122   // returns a new entry for "region_ind".
   123   SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
   125   // Returns the index of the next free entry in "_entries".
   126   int alloc_entry();
   127   // Declares the entry "fi" to be free.  (It must have already been
   128   // deleted from any bucket lists.
   129   void free_entry(int fi);
   131 public:
   132   RSHashTable(size_t capacity);
   133   ~RSHashTable();
   135   // Attempts to ensure that the given card_index in the given region is in
   136   // the sparse table.  If successful (because the card was already
   137   // present, or because it was successfullly added) returns "true".
   138   // Otherwise, returns "false" to indicate that the addition would
   139   // overflow the entry for the region.  The caller must transfer these
   140   // entries to a larger-capacity representation.
   141   bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
   143   bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
   144   bool delete_entry(RegionIdx_t region_id);
   146   bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
   148   void add_entry(SparsePRTEntry* e);
   150   void clear();
   152   size_t capacity() const      { return _capacity;       }
   153   size_t capacity_mask() const { return _capacity_mask;  }
   154   size_t occupied_entries() const { return _occupied_entries; }
   155   size_t occupied_cards() const   { return _occupied_cards;   }
   156   size_t mem_size() const;
   157   bool deleted() { return _deleted; }
   159   SparsePRTEntry* entry(int i) const { return &_entries[i]; }
   161   void print();
   163   static void add_to_deleted_list(RSHashTable* rsht);
   164   static RSHashTable* get_from_deleted_list();
   165 };
   167 // ValueObj because will be embedded in HRRS iterator.
   168 class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
   169   int _tbl_ind;         // [-1, 0.._rsht->_capacity)
   170   int _bl_ind;          // [-1, 0.._rsht->_capacity)
   171   short _card_ind;      // [0..CardsPerEntry)
   172   RSHashTable* _rsht;
   173   size_t _heap_bot_card_ind;
   175   enum SomePrivateConstants {
   176     CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift
   177   };
   179   // If the bucket list pointed to by _bl_ind contains a card, sets
   180   // _bl_ind to the index of that entry, and returns the card.
   181   // Otherwise, returns SparseEntry::NullEntry.
   182   CardIdx_t find_first_card_in_list();
   184   // Computes the proper card index for the card whose offset in the
   185   // current region (as indicated by _bl_ind) is "ci".
   186   // This is subject to errors when there is iteration concurrent with
   187   // modification, but these errors should be benign.
   188   size_t compute_card_ind(CardIdx_t ci);
   190 public:
   191   RSHashTableIter(size_t heap_bot_card_ind) :
   192     _tbl_ind(RSHashTable::NullEntry),
   193     _bl_ind(RSHashTable::NullEntry),
   194     _card_ind((SparsePRTEntry::CardsPerEntry-1)),
   195     _rsht(NULL),
   196     _heap_bot_card_ind(heap_bot_card_ind)
   197   {}
   199   void init(RSHashTable* rsht) {
   200     _rsht = rsht;
   201     _tbl_ind = -1; // So that first increment gets to 0.
   202     _bl_ind = RSHashTable::NullEntry;
   203     _card_ind = (SparsePRTEntry::CardsPerEntry-1);
   204   }
   206   bool has_next(size_t& card_index);
   207 };
   209 // Concurrent accesss to a SparsePRT must be serialized by some external
   210 // mutex.
   212 class SparsePRTIter;
   214 class SparsePRT VALUE_OBJ_CLASS_SPEC {
   215   //  Iterations are done on the _cur hash table, since they only need to
   216   //  see entries visible at the start of a collection pause.
   217   //  All other operations are done using the _next hash table.
   218   RSHashTable* _cur;
   219   RSHashTable* _next;
   221   HeapRegion* _hr;
   223   enum SomeAdditionalPrivateConstants {
   224     InitialCapacity = 16
   225   };
   227   void expand();
   229   bool _expanded;
   231   bool expanded() { return _expanded; }
   232   void set_expanded(bool b) { _expanded = b; }
   234   SparsePRT* _next_expanded;
   236   SparsePRT* next_expanded() { return _next_expanded; }
   237   void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }
   239   static SparsePRT* _head_expanded_list;
   241 public:
   242   SparsePRT(HeapRegion* hr);
   244   ~SparsePRT();
   246   size_t occupied() const { return _next->occupied_cards(); }
   247   size_t mem_size() const;
   249   // Attempts to ensure that the given card_index in the given region is in
   250   // the sparse table.  If successful (because the card was already
   251   // present, or because it was successfullly added) returns "true".
   252   // Otherwise, returns "false" to indicate that the addition would
   253   // overflow the entry for the region.  The caller must transfer these
   254   // entries to a larger-capacity representation.
   255   bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
   257   // If the table hold an entry for "region_ind",  Copies its
   258   // cards into "cards", which must be an array of length at least
   259   // "CardsPerEntry", and returns "true"; otherwise, returns "false".
   260   bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
   262   // If there is an entry for "region_ind", removes it and return "true";
   263   // otherwise returns "false."
   264   bool delete_entry(RegionIdx_t region_ind);
   266   // Clear the table, and reinitialize to initial capacity.
   267   void clear();
   269   // Ensure that "_cur" and "_next" point to the same table.
   270   void cleanup();
   272   // Clean up all tables on the expanded list.  Called single threaded.
   273   static void cleanup_all();
   274   RSHashTable* cur() const { return _cur; }
   276   void init_iterator(SparsePRTIter* sprt_iter);
   278   static void add_to_expanded_list(SparsePRT* sprt);
   279   static SparsePRT* get_from_expanded_list();
   281   bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
   282     return _next->contains_card(region_id, card_index);
   283   }
   285 #if 0
   286   void verify_is_cleared();
   287   void print();
   288 #endif
   289 };
   292 class SparsePRTIter: public /* RSHashTable:: */RSHashTableIter {
   293 public:
   294   SparsePRTIter(size_t heap_bot_card_ind) :
   295     /* RSHashTable:: */RSHashTableIter(heap_bot_card_ind)
   296   {}
   298   void init(const SparsePRT* sprt) {
   299     RSHashTableIter::init(sprt->cur());
   300   }
   301   bool has_next(size_t& card_index) {
   302     return RSHashTableIter::has_next(card_index);
   303   }
   304 };

mercurial