• 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 #include "ref_block.h"
16 
17 namespace panda::mem {
18 
RefBlock(RefBlock * prev)19 RefBlock::RefBlock(RefBlock *prev)
20 {
21     slots_ = START_VALUE;
22     prev_block_ = prev;
23 }
24 
Reset(RefBlock * prev)25 void RefBlock::Reset(RefBlock *prev)
26 {
27     slots_ = START_VALUE;
28     prev_block_ = prev;
29 }
30 
AddRef(const ObjectHeader * object,Reference::ObjectType type)31 Reference *RefBlock::AddRef(const ObjectHeader *object, Reference::ObjectType type)
32 {
33     ASSERT(!IsFull());
34     uint8_t index = GetFreeIndex();
35     Set(index, object);
36     auto *ref = reinterpret_cast<Reference *>(&refs_[index]);
37     ref = Reference::SetType(ref, type);
38     return ref;
39 }
40 
Remove(const Reference * ref)41 void RefBlock::Remove(const Reference *ref)
42 {
43     ASSERT(!IsEmpty());
44     ref = Reference::GetRefWithoutType(ref);
45 
46     auto ref_ptr = ToUintPtr(ref);
47     auto block_ptr = ToUintPtr(this);
48     auto index = (ref_ptr - block_ptr) / sizeof(ObjectPointer<ObjectHeader>);
49     ASSERT(IsBusyIndex(index));
50     slots_ |= static_cast<uint64_t>(1U) << index;
51     ASAN_POISON_MEMORY_REGION(refs_[index], sizeof(refs_[index]));
52 }
53 
VisitObjects(const GCRootVisitor & gc_root_visitor,mem::RootType rootType)54 void RefBlock::VisitObjects(const GCRootVisitor &gc_root_visitor, mem::RootType rootType)
55 {
56     for (auto *block : *this) {
57         if (block->IsEmpty()) {
58             continue;
59         }
60         for (size_t index = 0; index < REFS_IN_BLOCK; index++) {
61             if (block->IsBusyIndex(index)) {
62                 auto object_pointer = block->refs_[index];
63                 auto *obj = object_pointer.ReinterpretCast<ObjectHeader *>();
64                 ASSERT(obj->ClassAddr<BaseClass>() != nullptr);
65                 LOG(DEBUG, GC) << " Found root from ref-storage: " << mem::GetDebugInfoAboutObject(obj);
66                 gc_root_visitor({rootType, obj});
67             }
68         }
69     }
70 }
71 
UpdateMovedRefs()72 void RefBlock::UpdateMovedRefs()
73 {
74     for (auto *block : *this) {
75         if (block->IsEmpty()) {
76             continue;
77         }
78         for (size_t index = 0; index < REFS_IN_BLOCK; index++) {
79             if (!block->IsBusyIndex(index)) {
80                 continue;
81             }
82 
83             auto object_pointer = block->refs_[index];
84             auto *object = object_pointer.ReinterpretCast<ObjectHeader *>();
85             auto obj = reinterpret_cast<ObjectHeader *>(object);
86 
87             if (!obj->IsForwarded()) {
88                 continue;
89             }
90 
91             LOG(DEBUG, GC) << " Update pointer for obj: " << mem::GetDebugInfoAboutObject(obj);
92             ObjectHeader *forward_address = GetForwardAddress(obj);
93             block->refs_[index] = reinterpret_cast<ObjectHeader *>(forward_address);
94         }
95     }
96 }
97 
98 // used only for dumping and tests
GetAllReferencesInFrame()99 PandaVector<Reference *> RefBlock::GetAllReferencesInFrame()
100 {
101     PandaVector<Reference *> refs;
102     for (auto *block : *this) {
103         if (block->IsEmpty()) {
104             continue;
105         }
106         for (size_t index = 0; index < REFS_IN_BLOCK; index++) {
107             if (block->IsBusyIndex(index)) {
108                 auto *current_ref = reinterpret_cast<Reference *>(&block->refs_[index]);
109                 refs.push_back(current_ref);
110             }
111         }
112     }
113     return refs;
114 }
115 
GetFreeIndex()116 uint8_t RefBlock::GetFreeIndex()
117 {
118     ASSERT(!IsFull());
119     auto res = Ffs(slots_) - 1;
120 #ifndef NDEBUG
121     uint8_t index = 0;
122     while (IsBusyIndex(index)) {
123         index++;
124     }
125     ASSERT(index == res);
126 #endif
127     return res;
128 }
129 
Set(uint8_t index,const ObjectHeader * object)130 void RefBlock::Set(uint8_t index, const ObjectHeader *object)
131 {
132     ASSERT(IsFreeIndex(index));
133     ASAN_UNPOISON_MEMORY_REGION(refs_[index], sizeof(refs_[index]));
134     refs_[index] = object;
135     slots_ &= ~(static_cast<uint64_t>(1U) << index);
136 }
137 
IsFreeIndex(uint8_t index)138 bool RefBlock::IsFreeIndex(uint8_t index)
139 {
140     return !IsBusyIndex(index);
141 }
142 
IsBusyIndex(uint8_t index)143 bool RefBlock::IsBusyIndex(uint8_t index)
144 {
145     return ((slots_ >> index) & 1U) == 0;
146 }
147 
PrintBlock()148 void RefBlock::PrintBlock()
149 {
150     auto refs = GetAllReferencesInFrame();
151     for (const auto &ref : refs) {
152         std::cout << ref << " ";
153     }
154 }
155 
156 }  // namespace panda::mem
157