src/hotspot/share/gc/g1/g1CardTable.hpp
changeset 55510 3e31a8beaae4
parent 54110 f4f0dce5d0bb
child 59319 9ee940f1de90
equal deleted inserted replaced
55509:d58442b8abc1 55510:3e31a8beaae4
    42   void set_card_table(G1CardTable* card_table) { _card_table = card_table; }
    42   void set_card_table(G1CardTable* card_table) { _card_table = card_table; }
    43 
    43 
    44   virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled);
    44   virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled);
    45 };
    45 };
    46 
    46 
    47 class G1CardTable: public CardTable {
    47 class G1CardTable : public CardTable {
    48   friend class VMStructs;
    48   friend class VMStructs;
    49   friend class G1CardTableChangedListener;
    49   friend class G1CardTableChangedListener;
    50 
    50 
    51   G1CardTableChangedListener _listener;
    51   G1CardTableChangedListener _listener;
    52 
    52 
       
    53 public:
    53   enum G1CardValues {
    54   enum G1CardValues {
    54     g1_young_gen = CT_MR_BS_last_reserved << 1
    55     g1_young_gen = CT_MR_BS_last_reserved << 1,
       
    56 
       
    57     // During evacuation we use the card table to consolidate the cards we need to
       
    58     // scan for roots onto the card table from the various sources. Further it is
       
    59     // used to record already completely scanned cards to avoid re-scanning them
       
    60     // when incrementally evacuating the old gen regions of a collection set.
       
    61     // This means that already scanned cards should be preserved.
       
    62     //
       
    63     // The merge at the start of each evacuation round simply sets cards to dirty
       
    64     // that are clean; scanned cards are set to 0x1.
       
    65     //
       
    66     // This means that the LSB determines what to do with the card during evacuation
       
    67     // given the following possible values:
       
    68     //
       
    69     // 11111111 - clean, do not scan
       
    70     // 00000001 - already scanned, do not scan
       
    71     // 00000000 - dirty, needs to be scanned.
       
    72     //
       
    73     g1_card_already_scanned = 0x1
    55   };
    74   };
    56 
    75 
    57 public:
    76   static const size_t WordAllClean = SIZE_MAX;
       
    77   static const size_t WordAllDirty = 0;
       
    78 
       
    79   STATIC_ASSERT(BitsPerByte == 8);
       
    80   static const size_t WordAlreadyScanned = (SIZE_MAX / 255) * g1_card_already_scanned;
       
    81 
    58   G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() {
    82   G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() {
    59     _listener.set_card_table(this);
    83     _listener.set_card_table(this);
    60   }
       
    61   bool is_card_dirty(size_t card_index) {
       
    62     return _byte_map[card_index] == dirty_card_val();
       
    63   }
    84   }
    64 
    85 
    65   static CardValue g1_young_card_val() { return g1_young_gen; }
    86   static CardValue g1_young_card_val() { return g1_young_gen; }
    66 
    87 
    67 /*
       
    68    Claimed and deferred bits are used together in G1 during the evacuation
       
    69    pause. These bits can have the following state transitions:
       
    70    1. The claimed bit can be put over any other card state. Except that
       
    71       the "dirty -> dirty and claimed" transition is checked for in
       
    72       G1 code and is not used.
       
    73    2. Deferred bit can be set only if the previous state of the card
       
    74       was either clean or claimed. mark_card_deferred() is wait-free.
       
    75       We do not care if the operation is be successful because if
       
    76       it does not it will only result in duplicate entry in the update
       
    77       buffer because of the "cache-miss". So it's not worth spinning.
       
    78  */
       
    79 
       
    80   bool is_card_claimed(size_t card_index) {
       
    81     CardValue val = _byte_map[card_index];
       
    82     return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
       
    83   }
       
    84 
       
    85   inline void set_card_claimed(size_t card_index);
       
    86 
       
    87   void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN;
    88   void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN;
    88   void g1_mark_as_young(const MemRegion& mr);
    89   void g1_mark_as_young(const MemRegion& mr);
    89 
    90 
    90   bool mark_card_deferred(size_t card_index);
    91   size_t index_for_cardvalue(CardValue const* p) const {
       
    92     return pointer_delta(p, _byte_map, sizeof(CardValue));
       
    93   }
    91 
    94 
    92   bool is_card_deferred(size_t card_index) {
    95   // Mark the given card as Dirty if it is Clean.
    93     CardValue val = _byte_map[card_index];
    96   inline void mark_clean_as_dirty(size_t card_index);
    94     return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
    97 
    95   }
    98   // Change Clean cards in a (large) area on the card table as Dirty, preserving
       
    99   // already scanned cards. Assumes that most cards in that area are Clean.
       
   100   inline void mark_region_dirty(size_t start_card_index, size_t num_cards);
       
   101 
       
   102   // Mark the given range of cards as Scanned. All of these cards must be Dirty.
       
   103   inline void mark_as_scanned(size_t start_card_index, size_t num_cards);
       
   104 
       
   105   inline uint region_idx_for(CardValue* p);
    96 
   106 
    97   static size_t compute_size(size_t mem_region_size_in_words) {
   107   static size_t compute_size(size_t mem_region_size_in_words) {
    98     size_t number_of_slots = (mem_region_size_in_words / card_size_in_words);
   108     size_t number_of_slots = (mem_region_size_in_words / card_size_in_words);
    99     return ReservedSpace::allocation_align_size_up(number_of_slots);
   109     return ReservedSpace::allocation_align_size_up(number_of_slots);
   100   }
   110   }