• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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_RUNTIME_MEM_REF_BLOCK_H
16 #define PANDA_RUNTIME_MEM_REF_BLOCK_H
17 
18 #include <cstddef>
19 #include <limits>
20 
21 #include "include/object_header.h"
22 #include <libpandabase/mem/object_pointer.h>
23 #include "runtime/mem/refstorage/reference.h"
24 #include "runtime/mem/object_helpers.h"
25 #include "runtime/mem/gc/gc_root.h"
26 
27 namespace panda::mem::test {
28 class ReferenceStorageTest;
29 }  // namespace panda::mem::test
30 
31 namespace panda::mem {
32 
33 class RefBlock {
34     using SlotBitMap = uint64_t;
35 
36     class Iterator {
37         RefBlock *ref_block_;
38 
39     public:
Iterator(RefBlock * ref_block)40         explicit Iterator(RefBlock *ref_block) : ref_block_(ref_block) {}
41 
42         ~Iterator() = default;
43 
44         DEFAULT_COPY_SEMANTIC(Iterator);
45         DEFAULT_MOVE_SEMANTIC(Iterator);
46 
47         RefBlock *operator*() const
48         {
49             return ref_block_;
50         }
51 
52         Iterator &operator++()
53         {
54             ref_block_ = ref_block_->GetPrev();
55             return *this;
56         }
57 
58         const Iterator operator++(int)  // NOLINT(readability-const-return-type)
59         {
60             Iterator tmp = *this;
61             ++(*this);
62             return tmp;
63         }
64 
65         friend bool operator==(const Iterator &a, const Iterator &b)
66         {
67             return a.ref_block_ == b.ref_block_;
68         }
69 
70         friend bool operator!=(const Iterator &a, const Iterator &b)
71         {
72             return a.ref_block_ != b.ref_block_;
73         }
74     };
75 
76     static constexpr unsigned int REFS_IN_BLOCK = 60;
77     static constexpr SlotBitMap START_VALUE = std::numeric_limits<SlotBitMap>::max();
78     static constexpr SlotBitMap FINAL_VALUE =
79         std::numeric_limits<SlotBitMap>::max() & (~((static_cast<SlotBitMap>(1U) << REFS_IN_BLOCK) - 1U));
80 
81     // should be first field in the class
82     ObjectPointer<ObjectHeader> refs_[REFS_IN_BLOCK];  // NOLINT(modernize-avoid-c-arrays)
83 
84     // slots in the array. slot is free - bit=1, slot is busy - bit=0
85     SlotBitMap slots_ {START_VALUE};
86 
87     RefBlock *prev_block_ {nullptr};
88 
89 public:
90     explicit RefBlock(RefBlock *prev);
91 
RefBlock()92     RefBlock() : RefBlock(nullptr) {}
93 
Reset()94     void Reset()
95     {
96         Reset(nullptr);
97     }
98 
99     void Reset(RefBlock *prev);
100 
IsFull()101     bool IsFull() const
102     {
103         return slots_ == FINAL_VALUE;
104     }
105 
IsEmpty()106     bool IsEmpty() const
107     {
108         return slots_ == START_VALUE;
109     }
110 
111     Reference *AddRef(const ObjectHeader *object, Reference::ObjectType type);
112 
113     void Remove(const Reference *ref);
114 
GetPrev()115     RefBlock *GetPrev() const
116     {
117         return prev_block_;
118     }
119 
120     void VisitObjects(const GCRootVisitor &gc_root_visitor, mem::RootType rootType);
121 
122     void UpdateMovedRefs();
123 
124     // used only for dumping and tests
125     PandaVector<Reference *> GetAllReferencesInFrame();
126 
begin()127     Iterator begin()  // NOLINT(readability-identifier-naming)
128     {
129         return Iterator(this);
130     }
131 
end()132     Iterator end()  // NOLINT(readability-identifier-naming)
133     {
134         return Iterator(nullptr);
135     }
136 
137     ~RefBlock() = default;
138 
139     DEFAULT_COPY_SEMANTIC(RefBlock);
140     DEFAULT_MOVE_SEMANTIC(RefBlock);
141 
142 private:
143     uint8_t GetFreeIndex();
144 
145     void Set(uint8_t index, const ObjectHeader *object);
146 
147     bool IsFreeIndex(uint8_t index);
148 
149     bool IsBusyIndex(uint8_t index);
150 
151     void PrintBlock();
152 
153     // test purpose only, don't use in production
154 
DumpFrame()155     void DumpFrame()
156     {
157         std::cout << "Dump chain start --------------";
158         for (auto block : *this) {
159             std::cout << std::endl << "block: " << std::hex << &block << std::endl;
160             block->PrintBlock();
161         }
162         std::cout << std::endl << "Dump chain finish --------------" << std::endl;
163     }
164 
DumpBlock()165     void DumpBlock()
166     {
167         std::cout << "Dump block start --------------" << std::endl;
168         std::cout << std::endl << "block: " << std::hex << this << std::endl;
169         PrintBlock();
170         std::cout << std::endl << "Dump block finish --------------" << std::endl;
171     }
172     friend class panda::mem::test::ReferenceStorageTest;
173     friend class panda::mem::ReferenceStorage;
174 };
175 
176 }  // namespace panda::mem
177 
178 #endif  // PANDA_RUNTIME_MEM_REF_BLOCK_H
179