• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #ifndef PANDA_RUNTIME_MEM_GC_GC_BARRIER_SET_H_
17 #define PANDA_RUNTIME_MEM_GC_GC_BARRIER_SET_H_
18 
19 #include "libpandabase/mem/gc_barrier.h"
20 #include "runtime/include/mem/panda_containers.h"
21 #include "runtime/include/mem/panda_string.h"
22 
23 namespace panda::mem {
24 
25 /**
26  * Base barrier set
27  */
28 class GCBarrierSet {
29 public:
30     GCBarrierSet() = delete;
GCBarrierSet(mem::InternalAllocatorPtr allocator,BarrierType pre_type,BarrierType post_type)31     GCBarrierSet(mem::InternalAllocatorPtr allocator, BarrierType pre_type, BarrierType post_type)
32         : pre_type_(pre_type),
33           post_type_(post_type),
34           pre_operands_(allocator->Adapter()),
35           post_operands_(allocator->Adapter())
36     {
37     }
38 
39     NO_COPY_SEMANTIC(GCBarrierSet);
40     NO_MOVE_SEMANTIC(GCBarrierSet);
41     virtual ~GCBarrierSet() = 0;
42 
GetPreType()43     BarrierType GetPreType() const
44     {
45         ASSERT(IsPreBarrier(pre_type_));
46         return pre_type_;
47     }
48 
GetPostType()49     BarrierType GetPostType() const
50     {
51         ASSERT(IsPostBarrier(post_type_));
52         return post_type_;
53     }
54 
55     /**
56      * Pre barrier. Used by interpreter.
57      * @param obj_field_addr - address of field where we store. It can be unused in most cases
58      * @param pre_val_addr - reference currently(before store/load happened) stored in the field
59      */
60     virtual void PreBarrier(const void *obj_field_addr, void *pre_val_addr) = 0;
61 
62     /**
63      * Post barrier. Used by interpeter.
64      * @param obj_addr - address of field where we store
65      * @param val_addr - reference stored into or loaded from the field
66      */
67     virtual void PostBarrier(const void *obj_addr, void *val_addr) = 0;
68 
69     /**
70      * Post barrier for array write. Used by interpeter.
71      * @param obj_addr - address of the array object
72      * @param size - size of the array object
73      */
74     virtual void PostBarrierArrayWrite(const void *obj_addr, size_t size) = 0;
75 
76     /**
77      * Post barrier for writing in every field of an object. Used by interpeter.
78      * @param object_addr - address of the object
79      * @param size - size of the object
80      */
81     virtual void PostBarrierEveryObjectFieldWrite(const void *obj_addr, size_t size) = 0;
82 
83     /**
84      * Get barrier operand (literal, function pointer, address etc. See enum BarrierType for details.
85      * Should be used for barrier generation in Compiler.
86      * @param name - string with name of operand
87      * @return barrier operand (value is address or literal)
88      */
89     BarrierOperand GetBarrierOperand(BarrierPosition barrier_position, 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 barrier_position,std::string_view name,const BarrierOperand & barrier_operand)98     void AddBarrierOperand(BarrierPosition barrier_position, std::string_view name,
99                            const BarrierOperand &barrier_operand)
100     {
101         if (barrier_position == BarrierPosition::BARRIER_POSITION_PRE) {
102             ASSERT(pre_operands_.find(name) == pre_operands_.end());
103             pre_operands_.insert({name.data(), barrier_operand});
104         } else {
105             ASSERT(barrier_position == BarrierPosition::BARRIER_POSITION_POST);
106             ASSERT(post_operands_.find(name) == post_operands_.end());
107             post_operands_.insert({name.data(), barrier_operand});
108         }
109     }
110 
111 private:
112     BarrierType pre_type_;   // Type of PRE barrier.
113     BarrierType post_type_;  // Type of POST barrier.
114     PandaMap<PandaString, BarrierOperand> pre_operands_;
115     PandaMap<PandaString, BarrierOperand> post_operands_;
116 };
117 
118 /**
119  * BarrierSet with barriers do nothing
120  */
121 class GCDummyBarrierSet : public GCBarrierSet {
122 public:
GCDummyBarrierSet(mem::InternalAllocatorPtr allocator)123     explicit GCDummyBarrierSet(mem::InternalAllocatorPtr allocator)
124         : GCBarrierSet(allocator, BarrierType::PRE_WRB_NONE, BarrierType::POST_WRB_NONE)
125     {
126     }
127 
128     NO_COPY_SEMANTIC(GCDummyBarrierSet);
129     NO_MOVE_SEMANTIC(GCDummyBarrierSet);
130     ~GCDummyBarrierSet() override = default;
131 
PreBarrier(const void * obj_field_addr,void * pre_val_addr)132     void PreBarrier([[maybe_unused]] const void *obj_field_addr, [[maybe_unused]] void *pre_val_addr) override {}
133 
PostBarrier(const void * obj_addr,void * stored_val_addr)134     void PostBarrier([[maybe_unused]] const void *obj_addr, [[maybe_unused]] void *stored_val_addr) override {}
135 
PostBarrierArrayWrite(const void * obj_addr,size_t size)136     void PostBarrierArrayWrite([[maybe_unused]] const void *obj_addr, [[maybe_unused]] size_t size) override {}
137 
PostBarrierEveryObjectFieldWrite(const void * obj_addr,size_t size)138     void PostBarrierEveryObjectFieldWrite([[maybe_unused]] const void *obj_addr, [[maybe_unused]] size_t size) override
139     {
140     }
141 };
142 
143 class GCGenBarrierSet : public GCBarrierSet {
144 public:
GCGenBarrierSet(mem::InternalAllocatorPtr allocator,bool * concurrent_marking_flag,objRefProcessFunc pre_store_func,void * min_addr,uint8_t * card_table_addr,uint8_t card_bits,uint8_t dirty_card_value)145     GCGenBarrierSet(mem::InternalAllocatorPtr allocator, /* PRE ARGS: */ bool *concurrent_marking_flag,
146                     objRefProcessFunc pre_store_func, /* POST ARGS: */
147                     void *min_addr, uint8_t *card_table_addr, uint8_t card_bits, uint8_t dirty_card_value)
148         : GCBarrierSet(allocator, BarrierType::PRE_SATB_BARRIER, BarrierType::POST_INTERGENERATIONAL_BARRIER),
149           concurrent_marking_flag_(concurrent_marking_flag),
150           pre_store_func_(pre_store_func),
151           min_addr_(min_addr),
152           card_table_addr_(card_table_addr),
153           card_bits_(card_bits),
154           dirty_card_value_(dirty_card_value)
155     {
156         // PRE
157         AddBarrierOperand(
158             BarrierPosition::BARRIER_POSITION_PRE, "CONCURRENT_MARKING_ADDR",
159             BarrierOperand(BarrierOperandType::BOOL_ADDRESS, BarrierOperandValue(concurrent_marking_flag)));
160         AddBarrierOperand(
161             BarrierPosition::BARRIER_POSITION_PRE, "STORE_IN_BUFF_TO_MARK_FUNC",
162             BarrierOperand(BarrierOperandType::FUNC_WITH_OBJ_REF_ADDRESS, BarrierOperandValue(pre_store_func)));
163         // POST
164         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "MIN_ADDR",
165                           BarrierOperand(BarrierOperandType::ADDRESS, BarrierOperandValue(min_addr)));
166         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_TABLE_ADDR",
167                           BarrierOperand(BarrierOperandType::UINT8_ADDRESS, BarrierOperandValue(card_table_addr)));
168         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_BITS",
169                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(card_bits)));
170         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "DIRTY_VAL",
171                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(dirty_card_value)));
172     }
173 
174     void PreBarrier(const void *obj_field_addr, void *pre_val_addr) override;
175 
176     void PostBarrier(const void *obj_addr, void *stored_val_addr) override;
177 
178     void PostBarrierArrayWrite(const void *obj_addr, size_t size) override;
179 
180     void PostBarrierEveryObjectFieldWrite(const void *obj_addr, size_t size) override;
181 
182     ~GCGenBarrierSet() override = default;
183 
184     NO_COPY_SEMANTIC(GCGenBarrierSet);
185     NO_MOVE_SEMANTIC(GCGenBarrierSet);
186 
187 private:
188     // Store operands explicitly for interpreter perf
189     // PRE BARRIER
190     bool *concurrent_marking_flag_ {nullptr};
191     objRefProcessFunc pre_store_func_ {nullptr};
192     // POST BARRIER
193     void *min_addr_ {nullptr};            //! Minimal address used by VM. Used as a base for card index calculation
194     uint8_t *card_table_addr_ {nullptr};  //! Address of card table
195     uint8_t card_bits_ {0};               //! how many bits encoded by card (i.e. size covered by card = 2^card_bits_)
196     uint8_t dirty_card_value_ {0};        //! value of dirty card
197 };
198 
199 class GCG1BarrierSet : public GCBarrierSet {
200 public:
GCG1BarrierSet(mem::InternalAllocatorPtr allocator,bool * concurrent_marking_flag,objRefProcessFunc pre_store_func,void * min_addr,uint8_t * card_table_addr,uint8_t card_bits,uint8_t dirty_card_value,std::function<void (const void *,const void *)> post_func,size_t region_size_bits_count)201     GCG1BarrierSet(mem::InternalAllocatorPtr allocator, /* PRE ARGS: */ bool *concurrent_marking_flag,
202                    objRefProcessFunc pre_store_func, /* POST ARGS: */
203                    void *min_addr, uint8_t *card_table_addr, uint8_t card_bits, uint8_t dirty_card_value,
204                    std::function<void(const void *, const void *)> post_func, size_t region_size_bits_count)
205         : GCBarrierSet(allocator, BarrierType::PRE_SATB_BARRIER, BarrierType::POST_INTERGENERATIONAL_BARRIER),
206           concurrent_marking_flag_(concurrent_marking_flag),
207           pre_store_func_(pre_store_func),
208           min_addr_(min_addr),
209           card_table_addr_(card_table_addr),
210           card_bits_(card_bits),
211           dirty_card_value_(dirty_card_value),
212           post_func_(std::move(post_func)),
213           region_size_bits_count_(region_size_bits_count)
214     {
215         // PRE
216         AddBarrierOperand(
217             BarrierPosition::BARRIER_POSITION_PRE, "CONCURRENT_MARKING_ADDR",
218             BarrierOperand(BarrierOperandType::BOOL_ADDRESS, BarrierOperandValue(concurrent_marking_flag)));
219         AddBarrierOperand(
220             BarrierPosition::BARRIER_POSITION_PRE, "STORE_IN_BUFF_TO_MARK_FUNC",
221             BarrierOperand(BarrierOperandType::FUNC_WITH_OBJ_REF_ADDRESS, BarrierOperandValue(pre_store_func)));
222         // POST
223         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "MIN_ADDR",
224                           BarrierOperand(BarrierOperandType::ADDRESS, BarrierOperandValue(min_addr)));
225         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_TABLE_ADDR",
226                           BarrierOperand(BarrierOperandType::UINT8_ADDRESS, BarrierOperandValue(card_table_addr)));
227         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "CARD_BITS",
228                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(card_bits)));
229         AddBarrierOperand(BarrierPosition::BARRIER_POSITION_POST, "DIRTY_VAL",
230                           BarrierOperand(BarrierOperandType::UINT8_LITERAL, BarrierOperandValue(dirty_card_value)));
231     }
232 
233     void PreBarrier(const void *obj_field_addr, void *pre_val_addr) override;
234 
235     void PostBarrier(const void *obj_addr, void *stored_val_addr) override;
236 
237     void PostBarrierArrayWrite(const void *obj_addr, size_t size) override;
238 
239     void PostBarrierEveryObjectFieldWrite(const void *obj_addr, size_t size) override;
240 
241     ~GCG1BarrierSet() override = default;
242 
243     NO_COPY_SEMANTIC(GCG1BarrierSet);
244     NO_MOVE_SEMANTIC(GCG1BarrierSet);
245 
246 private:
247     using PostFuncT = std::function<void(const void *, const void *)>;
248     // Store operands explicitly for interpreter perf
249     // PRE BARRIER
250     bool *concurrent_marking_flag_ {nullptr};
251     objRefProcessFunc pre_store_func_ {nullptr};
252     // POST BARRIER
253     void *min_addr_ {nullptr};            //! Minimal address used by VM. Used as a base for card index calculation
254     uint8_t *card_table_addr_ {nullptr};  //! Address of card table
255     uint8_t card_bits_ {0};               //! how many bits encoded by card (i.e. size covered by card = 2^card_bits_)
256     uint8_t dirty_card_value_ {0};        //! value of dirty card
257     PostFuncT post_func_;                 //! function which is called for the post barrier if all conditions
258     size_t region_size_bits_count_ {0};   //! how much bits needed for the region
259 };
260 
261 }  // namespace panda::mem
262 
263 #endif  // PANDA_RUNTIME_MEM_GC_GC_BARRIER_SET_H_
264