1 /*
  2  * Copyright (c) 2000, 2026, 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_SHARED_CARDTABLEBARRIERSET_HPP
 26 #define SHARE_GC_SHARED_CARDTABLEBARRIERSET_HPP
 27 
 28 #include "gc/shared/barrierSet.hpp"
 29 #include "gc/shared/cardTable.hpp"
 30 #include "gc/shared/gc_globals.hpp"
 31 #include "memory/memRegion.hpp"
 32 #include "runtime/atomic.hpp"
 33 #include "utilities/align.hpp"
 34 
 35 // This kind of "BarrierSet" allows a "CollectedHeap" to detect and
 36 // enumerate ref fields that have been modified (since the last
 37 // enumeration.)
 38 
 39 // As it currently stands, this barrier is *imprecise*: when a ref field in
 40 // an object "o" is modified, the card table entry for the card containing
 41 // the head of "o" is dirtied, not necessarily the card containing the
 42 // modified field itself.  For object arrays, however, the barrier *is*
 43 // precise; only the card containing the modified element is dirtied.
 44 // Closures used to scan dirty cards should take these
 45 // considerations into account.
 46 
 47 class CardTableBarrierSet: public BarrierSet {
 48   // Some classes get to look at some private stuff.
 49   friend class VMStructs;
 50 
 51 protected:
 52   typedef CardTable::CardValue CardValue;
 53   Atomic<CardTable*> _card_table;
 54 
 55   CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler,
 56                       BarrierSetC1* barrier_set_c1,
 57                       BarrierSetC2* barrier_set_c2,
 58                       CardTable* card_table,
 59                       const BarrierSet::FakeRtti& fake_rtti);
 60 
 61 public:
 62   CardTableBarrierSet(CardTable* card_table);
 63   virtual ~CardTableBarrierSet();
 64 
 65   inline static CardTableBarrierSet* barrier_set() {
 66     return barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
 67   }
 68 
 69   template <DecoratorSet decorators, typename T>
 70   inline void write_ref_field_pre(T* addr) {}
 71 
 72   // Record a reference update. Note that these versions are precise!
 73   // The scanning code has to handle the fact that the write barrier may be
 74   // either precise or imprecise. We make non-virtual inline variants of
 75   // these functions here for performance.
 76   template <DecoratorSet decorators, typename T>
 77   inline void write_ref_field_post(T *addr);
 78 
 79   // Causes all refs in "mr" to be assumed to be modified (by this JavaThread).
 80   virtual void write_region(MemRegion mr);
 81 
 82   // Operations on arrays, or general regions (e.g., for "clone") may be
 83   // optimized by some barriers.
 84 
 85   // Below length is the # array elements being written
 86   virtual void write_ref_array_pre(oop* dst, size_t length,
 87                                    bool dest_uninitialized) {}
 88   virtual void write_ref_array_pre(narrowOop* dst, size_t length,
 89                                    bool dest_uninitialized) {}
 90   // Below count is the # array elements being written, starting
 91   // at the address "start", which may not necessarily be HeapWord-aligned
 92   inline void write_ref_array(HeapWord* start, size_t count);
 93 
 94   CardTable* card_table() { return _card_table.load_relaxed(); }
 95   CardTable* card_table() const { return _card_table.load_relaxed(); }
 96 
 97   CardValue* card_table_base_const() const {
 98     assert(UseSerialGC || UseParallelGC, "Only these GCs have constant card table base");
 99     return card_table()->byte_map_base();
100   }
101 
102   virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj);
103 
104   virtual void print_on(outputStream* st) const;
105 
106   template <DecoratorSet decorators, typename BarrierSetT = CardTableBarrierSet>
107   class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> {
108     typedef BarrierSet::AccessBarrier<decorators, BarrierSetT> Raw;
109 
110   public:
111     template <typename T>
112     static void oop_store_in_heap(T* addr, oop value);
113     template <typename T>
114     static oop oop_atomic_cmpxchg_in_heap(T* addr, oop compare_value, oop new_value);
115     template <typename T>
116     static oop oop_atomic_xchg_in_heap(T* addr, oop new_value);
117 
118     template <typename T>
119     static OopCopyResult oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw,
120                                                arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
121                                                size_t length);
122 
123     static void clone_in_heap(oop src, oop dst, size_t size);
124 
125     static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) {
126       oop_store_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), value);
127     }
128 
129     static oop oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) {
130       return oop_atomic_xchg_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), new_value);
131     }
132 
133     static oop oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) {
134       return oop_atomic_cmpxchg_in_heap(AccessInternal::oop_field_addr<decorators>(base, offset), compare_value, new_value);
135     }
136   };
137 };
138 
139 template<>
140 struct BarrierSet::GetName<CardTableBarrierSet> {
141   static const BarrierSet::Name value = BarrierSet::CardTableBarrierSet;
142 };
143 
144 template<>
145 struct BarrierSet::GetType<BarrierSet::CardTableBarrierSet> {
146   typedef ::CardTableBarrierSet type;
147 };
148 
149 #endif // SHARE_GC_SHARED_CARDTABLEBARRIERSET_HPP