• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef PANDA_GC_BARRIER_H
16 #define PANDA_GC_BARRIER_H
17 
18 #include "libpandabase/mem/gc_barrier.h"
19 #include "libpandabase/mem/ringbuf/lock_free_ring_buffer.h"
20 #include "runtime/include/mem/panda_containers.h"
21 #include "runtime/include/mem/panda_string.h"
22 #include "runtime/mem/gc/card_table.h"
23 
24 namespace ark::mem {
25 
26 /// Base barrier set
27 class GCBarrierSet {
28 public:
29     GCBarrierSet() = delete;
GCBarrierSet(mem::InternalAllocatorPtr allocator,BarrierType preType,BarrierType postType)30     GCBarrierSet(mem::InternalAllocatorPtr allocator, BarrierType preType, BarrierType postType)
31         : preType_(preType),
32           postType_(postType),
33           preOperands_(allocator->Adapter()),
34           postOperands_(allocator->Adapter())
35     {
36     }
37 
38     NO_COPY_SEMANTIC(GCBarrierSet);
39     NO_MOVE_SEMANTIC(GCBarrierSet);
40     virtual ~GCBarrierSet() = 0;
41 
GetPreType()42     BarrierType GetPreType() const
43     {
44         ASSERT(IsPreBarrier(preType_));
45         return preType_;
46     }
47 
GetPostType()48     BarrierType GetPostType() const
49     {
50         ASSERT(IsPostBarrier(postType_));
51         return postType_;
52     }
53 
IsPreBarrierEnabled()54     virtual bool IsPreBarrierEnabled()
55     {
56         return !mem::IsEmptyBarrier(preType_);
57     }
58 
59     /**
60      * Pre barrier. Used by interpreter.
61      * @param pre_val_addr - reference currently(before store/load happened) stored in the field
62      */
63     virtual void PreBarrier(void *preValAddr) = 0;
64 
65     /**
66      * Post barrier. Used by interpeter.
67      * @param obj_addr - address of object whose field we change
68      * @param offset   - field offset
69      * @param val_addr - reference stored into or loaded from the field
70      */
71     virtual void PostBarrier(const void *objAddr, size_t offset, void *valAddr) = 0;
72 
73     /**
74      * Post barrier for range write. Used by interpeter.
75      * @param obj_addr - address of the object
76      * @param offset - offset from obj_addr
77      * @param count - written bytes count
78      */
79     virtual void PostBarrier(const void *objAddr, size_t offset, size_t count) = 0;
80 
81     /**
82      * Get barrier operand (literal, function pointer, address etc. See enum BarrierType for details.
83      * Should be used for barrier generation in Compiler.
84      * @param name - string with name of operand
85      * @return barrier operand (value is address or literal)
86      */
87     BarrierOperand GetBarrierOperand(BarrierPosition barrierPosition, std::string_view name);
88 
89     BarrierOperand GetPostBarrierOperand(std::string_view name);
90 
91 protected:
92     /**
93      * Add barrier operand if there are no operands with this name
94      * @param barrier_position - pre or post position of barrier with added operand
95      * @param name - name of operand
96      * @param barrier_operand - operand
97      */
AddBarrierOperand(BarrierPosition barrierPosition,std::string_view name,const BarrierOperand & barrierOperand)98     void AddBarrierOperand(BarrierPosition barrierPosition, std::string_view name, const BarrierOperand &barrierOperand)
99     {
100         if (barrierPosition == BarrierPosition::BARRIER_POSITION_PRE) {
101             ASSERT(preOperands_.find(name) == preOperands_.end());
102             preOperands_.insert({name.data(), barrierOperand});
103         } else {
104             ASSERT(barrierPosition == BarrierPosition::BARRIER_POSITION_POST);
105             ASSERT(postOperands_.find(name) == postOperands_.end());
106             postOperands_.insert({name.data(), barrierOperand});
107         }
108     }
109 
110 private:
111     BarrierType preType_;   // Type of PRE barrier.
112     BarrierType postType_;  // Type of POST barrier.
113     PandaMap<PandaString, BarrierOperand> preOperands_;
114     PandaMap<PandaString, BarrierOperand> postOperands_;
115 };
116 
117 /// BarrierSet with barriers do nothing
118 class GCDummyBarrierSet : public GCBarrierSet {
119 public:
GCDummyBarrierSet(mem::InternalAllocatorPtr allocator)120     explicit GCDummyBarrierSet(mem::InternalAllocatorPtr allocator)
121         : GCBarrierSet(allocator, BarrierType::PRE_WRB_NONE, BarrierType::POST_WRB_NONE)
122     {
123     }
124 
125     NO_COPY_SEMANTIC(GCDummyBarrierSet);
126     NO_MOVE_SEMANTIC(GCDummyBarrierSet);
127     ~GCDummyBarrierSet() override = default;
128 
PreBarrier(void * preValAddr)129     void PreBarrier([[maybe_unused]] void *preValAddr) override {}
130 
PostBarrier(const void * objAddr,size_t offset,void * storedValAddr)131     void PostBarrier([[maybe_unused]] const void *objAddr, [[maybe_unused]] size_t offset,
132                      [[maybe_unused]] void *storedValAddr) override
133     {
134     }
135 
PostBarrier(const void * objAddr,size_t offset,size_t count)136     void PostBarrier([[maybe_unused]] const void *objAddr, [[maybe_unused]] size_t offset,
137                      [[maybe_unused]] size_t count) override
138     {
139     }
140 };
141 
142 class GCGenBarrierSet : public GCBarrierSet {
143 public:
GCGenBarrierSet(mem::InternalAllocatorPtr allocator,CardTable * cardTable,uint8_t cardBits,uint8_t dirtyCardValue)144     GCGenBarrierSet(mem::InternalAllocatorPtr allocator,
145                     /* POST ARGS: */
146                     CardTable *cardTable, uint8_t cardBits, uint8_t dirtyCardValue)
147         : GCBarrierSet(allocator, BarrierType::PRE_WRB_NONE, BarrierType::POST_INTERGENERATIONAL_BARRIER),
148           minAddr_(ToVoidPtr(cardTable->GetMinAddress())),
149           cardTableAddr_(reinterpret_cast<uint8_t *>(*cardTable->begin())),
150           cardBits_(cardBits),
151           dirtyCardValue_(dirtyCardValue),
152           cardTable_(cardTable)
153     {
154         // POST
155         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "MIN_ADDR",
156                           BarrierOperand(BarrierOperandType::ADDRESS, BarrierOperandValue(minAddr_)));
157         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_TABLE_ADDR",
158                           BarrierOperand(BarrierOperandType::UINT8_ADDRESS, BarrierOperandValue(cardTableAddr_)));
159         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_BITS",
160                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(cardBits)));
161         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "DIRTY_VAL",
162                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(dirtyCardValue)));
163     }
164 
165     void PreBarrier(void *preValAddr) override;
166 
167     void PostBarrier(const void *objAddr, size_t offset, void *storedValAddr) override;
168 
169     void PostBarrier(const void *objAddr, size_t offset, size_t count) override;
170 
171     ~GCGenBarrierSet() override = default;
172 
173     NO_COPY_SEMANTIC(GCGenBarrierSet);
174     NO_MOVE_SEMANTIC(GCGenBarrierSet);
175 
176 private:
177     // Store operands explicitly for interpreter perf
178     // POST BARRIER
179     /// Minimal address used by VM. Used as a base for card index calculation
180     void *minAddr_ {nullptr};
181     /// Address of card table
182     uint8_t *cardTableAddr_ {nullptr};
183     /// How many bits encoded by card (i.e. size covered by card = 2^card_bits_)
184     uint8_t cardBits_ {0};
185     /// Value of dirty card
186     uint8_t dirtyCardValue_ {0};
187     FIELD_UNUSED CardTable *cardTable_ {nullptr};
188 };
189 
190 class GCG1BarrierSet : public GCBarrierSet {
191 public:
192     using ThreadLocalCardQueues = PandaVector<CardTable::CardPtr>;
193     static constexpr size_t G1_POST_BARRIER_RING_BUFFER_SIZE = 1024 * 8;
194     using G1PostBarrierRingBufferType = mem::LockFreeBuffer<mem::CardTable::CardPtr, G1_POST_BARRIER_RING_BUFFER_SIZE>;
195 
GCG1BarrierSet(mem::InternalAllocatorPtr allocator,ObjRefProcessFunc preStoreFunc,ObjTwoRefProcessFunc postFunc,uint8_t regionSizeBitsCount,CardTable * cardTable,ThreadLocalCardQueues * updatedRefsQueue,os::memory::Mutex * queueLock)196     GCG1BarrierSet(mem::InternalAllocatorPtr allocator,
197                    // PRE ARGS:
198                    ObjRefProcessFunc preStoreFunc,
199                    // POST ARGS:
200                    ObjTwoRefProcessFunc postFunc, uint8_t regionSizeBitsCount, CardTable *cardTable,
201                    ThreadLocalCardQueues *updatedRefsQueue, os::memory::Mutex *queueLock)
202         : GCBarrierSet(allocator, BarrierType::PRE_SATB_BARRIER, BarrierType::POST_INTERREGION_BARRIER),
203           preStoreFunc_(preStoreFunc),
204           postFunc_(postFunc),
205           regionSizeBitsCount_(regionSizeBitsCount),
206           cardTable_(cardTable),
207           minAddr_(ToVoidPtr(cardTable->GetMinAddress())),
208           updatedRefsQueue_(updatedRefsQueue),
209           queueLock_(queueLock)
210     {
211         ASSERT(preStoreFunc_ != nullptr);
212         ASSERT(postFunc_ != nullptr);
213         // PRE
214         AddBarrierOperand(
215             BarrierPosition::BARRIER_POSITION_PRE, "STORE_IN_BUFF_TO_MARK_FUNC",
216             BarrierOperand(BarrierOperandType::FUNC_WITH_OBJ_REF_ADDRESS, BarrierOperandValue(preStoreFunc_)));
217         // POST
218         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "REGION_SIZE_BITS",
219                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(regionSizeBitsCount_)));
220         AddBarrierOperand(
221             BarrierPosition::BARRIER_POSITION_POST, "UPDATE_CARD_FUNC",
222             BarrierOperand(BarrierOperandType::FUNC_WITH_TWO_OBJ_REF_ADDRESSES, BarrierOperandValue(postFunc_)));
223         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_TABLE_ADDR",
224                           BarrierOperand(BarrierOperandType::UINT8_ADDRESS,
225                                          BarrierOperandValue(reinterpret_cast<uint8_t *>(*cardTable->begin()))));
226         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "MIN_ADDR",
227                           BarrierOperand(BarrierOperandType::ADDRESS, BarrierOperandValue(minAddr_)));
228     }
229 
230     bool IsPreBarrierEnabled() override;
231 
232     void PreBarrier(void *preValAddr) override;
233 
234     void PostBarrier(const void *objAddr, size_t offset, void *storedValAddr) override;
235 
236     void PostBarrier(const void *objAddr, size_t offset, size_t count) override;
237 
238     void Enqueue(CardTable::CardPtr card);
239 
240     ~GCG1BarrierSet() override = default;
241 
GetCardTable()242     CardTable *GetCardTable() const
243     {
244         return cardTable_;
245     }
246 
247     NO_COPY_SEMANTIC(GCG1BarrierSet);
248     NO_MOVE_SEMANTIC(GCG1BarrierSet);
249 
250 private:
251     void Invalidate(CardTable::CardPtr begin, CardTable::CardPtr last);
252     using PostFuncT = std::function<void(const void *, const void *)> *;
253     // Store operands explicitly for interpreter perf
254     // PRE BARRIER
255     ObjRefProcessFunc preStoreFunc_ {nullptr};
256     // POST BARRIER
257     /// Function which is called for the post barrier if all conditions
258     ObjTwoRefProcessFunc postFunc_;
259     /// How much bits needed for the region
260     uint8_t regionSizeBitsCount_ {0};
261     /// Card table pointer
262     CardTable *cardTable_ {nullptr};
263     /// Minimal address used by VM. Used as a base for card index calculation
264     void *minAddr_ {nullptr};
265     ThreadLocalCardQueues *updatedRefsQueue_;
266     os::memory::Mutex *queueLock_;
267 };
268 
269 }  // namespace ark::mem
270 
271 #endif  // PANDA_GC_BARRIER_H
272