1 /*
   2  * Copyright (c) 2001, 2019, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_GC_G1_G1CARDTABLE_HPP
  26 #define SHARE_GC_G1_G1CARDTABLE_HPP
  27 
  28 #include "gc/g1/g1RegionToSpaceMapper.hpp"
  29 #include "gc/shared/cardTable.hpp"
  30 #include "oops/oopsHierarchy.hpp"
  31 #include "utilities/macros.hpp"
  32 
  33 class G1CardTable;
  34 class G1RegionToSpaceMapper;
  35 
  36 class G1CardTableChangedListener : public G1MappingChangedListener {
  37  private:
  38   G1CardTable* _card_table;
  39  public:
  40   G1CardTableChangedListener() : _card_table(NULL) { }
  41 
  42   void set_card_table(G1CardTable* card_table) { _card_table = card_table; }
  43 
  44   virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled);
  45 };
  46 
  47 class G1CardTable : public CardTable {
  48   friend class VMStructs;
  49   friend class G1CardTableChangedListener;
  50 
  51   G1CardTableChangedListener _listener;
  52 
  53 public:
  54   enum G1CardValues {
  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
  74   };
  75 
  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 
  82   G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() {
  83     _listener.set_card_table(this);
  84   }
  85 
  86   static CardValue g1_young_card_val() { return g1_young_gen; }
  87 
  88   void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN;
  89   void g1_mark_as_young(const MemRegion& mr);
  90 
  91   size_t index_for_cardvalue(CardValue const* p) const {
  92     return pointer_delta(p, _byte_map, sizeof(CardValue));
  93   }
  94 
  95   // Mark the given card as Dirty if it is Clean.
  96   inline void mark_clean_as_dirty(size_t card_index);
  97 
  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);
 106 
 107   static size_t compute_size(size_t mem_region_size_in_words) {
 108     size_t number_of_slots = (mem_region_size_in_words / card_size_in_words);
 109     return ReservedSpace::allocation_align_size_up(number_of_slots);
 110   }
 111 
 112   // Returns how many bytes of the heap a single byte of the Card Table corresponds to.
 113   static size_t heap_map_factor() { return card_size; }
 114 
 115   void initialize() {}
 116   void initialize(G1RegionToSpaceMapper* mapper);
 117 
 118   virtual void resize_covered_region(MemRegion new_region) { ShouldNotReachHere(); }
 119 
 120   virtual bool is_in_young(oop obj) const;
 121 };
 122 
 123 #endif // SHARE_GC_G1_G1CARDTABLE_HPP