• 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 #include "runtime/mem/gc/gc_root.h"
17 
18 #include "libpandafile/panda_cache.h"
19 #include "runtime/include/object_header.h"
20 #include "runtime/include/runtime.h"
21 #include "runtime/include/stack_walker-inl.h"
22 #include "runtime/mem/refstorage/reference_storage.h"
23 #include "runtime/mem/gc/card_table-inl.h"
24 #include "runtime/mem/gc/gc.h"
25 #include "runtime/mem/object_helpers.h"
26 #include "runtime/mem/refstorage/global_object_storage.h"
27 #include "runtime/include/panda_vm.h"
28 
29 namespace panda::mem {
30 
GCRoot(RootType type,ObjectHeader * obj)31 GCRoot::GCRoot(RootType type, ObjectHeader *obj)
32 {
33     type_ = type;
34     from_object_ = nullptr;
35     object_ = obj;
36 }
37 
GCRoot(RootType type,ObjectHeader * from_object,ObjectHeader * obj)38 GCRoot::GCRoot(RootType type, ObjectHeader *from_object, ObjectHeader *obj)
39 {
40     ASSERT((from_object != nullptr && type == RootType::ROOT_TENURED) || type != RootType::ROOT_TENURED);
41     type_ = type;
42     from_object_ = from_object;
43     object_ = obj;
44 }
45 
GetType() const46 RootType GCRoot::GetType() const
47 {
48     return type_;
49 }
50 
GetObjectHeader() const51 ObjectHeader *GCRoot::GetObjectHeader() const
52 {
53     return object_;
54 }
55 
GetFromObjectHeader() const56 ObjectHeader *GCRoot::GetFromObjectHeader() const
57 {
58     ASSERT((from_object_ != nullptr && type_ == RootType::ROOT_TENURED) || type_ != RootType::ROOT_TENURED);
59     return from_object_;
60 }
61 
operator <<(std::ostream & os,const GCRoot & root)62 std::ostream &operator<<(std::ostream &os, const GCRoot &root)
63 {
64     switch (root.GetType()) {
65         case RootType::ROOT_CLASS:
66             os << "ROOT CLASS";
67             break;
68         case RootType::ROOT_FRAME:
69             os << "ROOT FRAME";
70             break;
71         case RootType::ROOT_THREAD:
72             os << "ROOT THREAD";
73             break;
74         case RootType::ROOT_TENURED:
75             os << "ROOT TENURED";
76             break;
77         case RootType::ROOT_JNI_GLOBAL:
78             os << "ROOT JNI GLOBAL";
79             break;
80         case RootType::ROOT_JNI_LOCAL:
81             os << "ROOT JNI_LOCAL";
82             break;
83         case RootType::ROOT_AOT_STRING_SLOT:
84             os << "ROOT AOT_STRING_SLOT";
85             break;
86         case RootType::ROOT_UNKNOWN:
87         default:
88             LOG(FATAL, GC) << "ROOT UNKNOWN";
89             break;
90     }
91     os << std::hex << " " << root.GetObjectHeader() << std::endl;
92     return os;
93 }
94 
95 template <class LanguageConfig>
VisitNonHeapRoots(const GCRootVisitor & gc_root_visitor,VisitGCRootFlags flags) const96 void RootManager<LanguageConfig>::VisitNonHeapRoots(const GCRootVisitor &gc_root_visitor, VisitGCRootFlags flags) const
97 {
98     VisitLocalRoots(gc_root_visitor);
99     VisitClassRoots(gc_root_visitor, flags);
100     VisitClassLinkerContextRoots(gc_root_visitor);
101     VisitVmRoots(gc_root_visitor);
102     vm_->GetGlobalObjectStorage()->VisitObjects(gc_root_visitor, mem::RootType::ROOT_JNI_GLOBAL);
103 }
104 
105 template <class LanguageConfig>
VisitCardTableRoots(CardTable * card_table,ObjectAllocatorBase * allocator,GCRootVisitor root_visitor,MemRangeChecker range_checker,ObjectChecker range_object_checker,ObjectChecker from_object_checker,uint32_t processed_flag) const106 void RootManager<LanguageConfig>::VisitCardTableRoots(CardTable *card_table, ObjectAllocatorBase *allocator,
107                                                       GCRootVisitor root_visitor, MemRangeChecker range_checker,
108                                                       ObjectChecker range_object_checker,
109                                                       ObjectChecker from_object_checker, uint32_t processed_flag) const
110 {
111     card_table->VisitMarked(
112         [&allocator, &root_visitor, &range_checker, &range_object_checker, &from_object_checker,
113          &card_table](MemRange mem_range) {
114             if (range_checker(mem_range)) {
115                 auto objects_in_range_visitor = [&root_visitor, &range_object_checker,
116                                                  &from_object_checker](ObjectHeader *object_header) {
117                     auto traverse_object_in_range = [&root_visitor, &range_object_checker](
118                                                         ObjectHeader *from_object, ObjectHeader *object_to_traverse) {
119                         if (range_object_checker(object_to_traverse)) {
120                             // The weak references from dynobjects should not be regarded as roots.
121                             TaggedValue value(object_to_traverse);
122                             if (!value.IsWeak()) {
123                                 root_visitor(GCRoot(RootType::ROOT_TENURED, from_object, object_to_traverse));
124                             }
125                         }
126                     };
127                     if (from_object_checker(object_header)) {
128                         ObjectHelpers<LanguageConfig::LANG_TYPE>::TraverseAllObjects(object_header,
129                                                                                      traverse_object_in_range);
130                     }
131                 };
132                 allocator->IterateOverObjectsInRange(mem_range, objects_in_range_visitor);
133             } else {
134                 card_table->MarkCard(mem_range.GetStartAddress());
135             }
136         },
137         processed_flag);
138 }
139 
140 template <class LanguageConfig>
VisitRootsForThread(ManagedThread * thread,const GCRootVisitor & gc_root_visitor) const141 void RootManager<LanguageConfig>::VisitRootsForThread(ManagedThread *thread, const GCRootVisitor &gc_root_visitor) const
142 {
143     LOG(DEBUG, GC) << "Start collecting roots for thread " << thread->GetId();
144 
145     thread->VisitGCRoots([&gc_root_visitor](ObjectHeader *obj) {
146         LOG(DEBUG, GC) << " Found root for thread" << GetDebugInfoAboutObject(obj);
147         gc_root_visitor({RootType::ROOT_THREAD, obj});
148     });
149     LOG(DEBUG, GC) << "Finish collecting roots for thread " << thread->GetId();
150 }
151 
152 template <class LanguageConfig>
VisitLocalRoots(const GCRootVisitor & gc_root_visitor) const153 void RootManager<LanguageConfig>::VisitLocalRoots(const GCRootVisitor &gc_root_visitor) const
154 {
155     auto thread_visitor = [this, &gc_root_visitor](ManagedThread *thread) {
156         VisitRootsForThread(thread, gc_root_visitor);
157         for (StackWalker stack(thread); stack.HasFrame(); stack.NextFrame()) {
158             LOG(DEBUG, GC) << " VisitRoots frame " << std::hex << stack.GetFp();
159             stack.IterateObjects([this, &gc_root_visitor](auto &vreg) {
160                 VisitRegisterRoot(vreg, gc_root_visitor);
161                 return true;
162             });
163         }
164         return true;
165     };
166     if constexpr (LanguageConfig::MT_MODE == MT_MODE_MULTI) {  // NOLINT
167         vm_->GetThreadManager()->EnumerateThreads(thread_visitor, static_cast<unsigned int>(EnumerationFlag::ALL));
168     } else {  // NOLINT
169         thread_visitor(ManagedThread::GetCurrent());
170     }
171 }
172 
173 template <class LanguageConfig>
VisitRegisterRoot(const Frame::VRegister & v_register,const GCRootVisitor & gc_root_visitor) const174 void RootManager<LanguageConfig>::VisitRegisterRoot(const Frame::VRegister &v_register,
175                                                     const GCRootVisitor &gc_root_visitor) const
176 {
177     if (UNLIKELY(v_register.HasObject())) {
178         ObjectHeader *object_header = v_register.GetReference();
179         if (object_header != nullptr) {
180             LOG(DEBUG, GC) << " Found root for register" << GetDebugInfoAboutObject(object_header);
181             gc_root_visitor({RootType::ROOT_FRAME, object_header});
182         }
183     }
184 }
185 
186 template <class LanguageConfig>
VisitVmRoots(const GCRootVisitor & gc_root_visitor) const187 void RootManager<LanguageConfig>::VisitVmRoots(const GCRootVisitor &gc_root_visitor) const
188 {
189     vm_->VisitVmRoots(gc_root_visitor);
190 }
191 
192 template <class LanguageConfig>
UpdateVmRefs()193 void RootManager<LanguageConfig>::UpdateVmRefs()
194 {
195     vm_->UpdateVmRefs();
196 }
197 
198 template <class LanguageConfig>
UpdateGlobalObjectStorage()199 void RootManager<LanguageConfig>::UpdateGlobalObjectStorage()
200 {
201     vm_->GetGlobalObjectStorage()->UpdateMovedRefs();
202 }
203 
204 template <class LanguageConfig>
VisitClassRoots(const GCRootVisitor & gc_root_visitor,VisitGCRootFlags flags) const205 void RootManager<LanguageConfig>::VisitClassRoots(const GCRootVisitor &gc_root_visitor, VisitGCRootFlags flags) const
206 {
207     if constexpr (LanguageConfig::LANG_TYPE == LANG_TYPE_DYNAMIC) {  // NOLINT
208         // Dynamic languages have not class roots
209         return;
210     }
211 
212     LOG(DEBUG, GC) << "Start collecting roots for classes";
213     auto class_linker = Runtime::GetCurrent()->GetClassLinker();
214     auto class_root_visitor = [&gc_root_visitor](Class *cls) {
215         gc_root_visitor({RootType::ROOT_CLASS, cls->GetManagedObject()});
216         LOG(DEBUG, GC) << " Found class root " << GetDebugInfoAboutObject(cls->GetManagedObject());
217         return true;
218     };
219     auto *extension = class_linker->GetExtension(LanguageConfig::LANG);
220     extension->EnumerateClasses(class_root_visitor, flags);
221     LOG(DEBUG, GC) << "Finish collecting roots for classes";
222 }
223 
224 template <class LanguageConfig>
UpdateThreadLocals()225 void RootManager<LanguageConfig>::UpdateThreadLocals()
226 {
227     LOG(DEBUG, GC) << "=== ThreadLocals Update moved. BEGIN ===";
228     if constexpr (LanguageConfig::MT_MODE == MT_MODE_MULTI) {  // NOLINT
229         vm_->GetThreadManager()->EnumerateThreads(
230             [](MTManagedThread *thread) {
231                 thread->UpdateGCRoots();
232                 return true;
233             },
234             static_cast<unsigned int>(EnumerationFlag::ALL));
235     } else {  // NOLINT
236         vm_->GetAssociatedThread()->UpdateGCRoots();
237     }
238     LOG(DEBUG, GC) << "=== ThreadLocals Update moved. END ===";
239 }
240 
241 template <class LanguageConfig>
VisitClassLinkerContextRoots(const GCRootVisitor & gc_root_visitor) const242 void RootManager<LanguageConfig>::VisitClassLinkerContextRoots(const GCRootVisitor &gc_root_visitor) const
243 {
244     LOG(DEBUG, GC) << "Start collecting roots for class linker contexts";
245     auto class_linker = Runtime::GetCurrent()->GetClassLinker();
246     auto *extension = class_linker->GetExtension(LanguageConfig::LANG);
247     extension->EnumerateContexts([&gc_root_visitor](ClassLinkerContext *ctx) {
248         ctx->VisitGCRoots([&gc_root_visitor](ObjectHeader *obj) {
249             LOG(DEBUG, GC) << " Found root for class linker context " << GetDebugInfoAboutObject(obj);
250             gc_root_visitor({RootType::ROOT_CLASS_LINKER, obj});
251         });
252         return true;
253     });
254     LOG(DEBUG, GC) << "Finish collecting roots for class linker contexts";
255 }
256 
257 template <class LanguageConfig>
UpdateClassLinkerContextRoots()258 void RootManager<LanguageConfig>::UpdateClassLinkerContextRoots()
259 {
260     auto class_linker = Runtime::GetCurrent()->GetClassLinker();
261     auto *extension = class_linker->GetExtension(LanguageConfig::LANG);
262     extension->EnumerateContexts([](ClassLinkerContext *ctx) {
263         ctx->UpdateGCRoots();
264         return true;
265     });
266 }
267 
operator &(VisitGCRootFlags left,VisitGCRootFlags right)268 uint32_t operator&(VisitGCRootFlags left, VisitGCRootFlags right)
269 {
270     return static_cast<uint32_t>(left) & static_cast<uint32_t>(right);
271 }
272 
operator |(VisitGCRootFlags left,VisitGCRootFlags right)273 VisitGCRootFlags operator|(VisitGCRootFlags left, VisitGCRootFlags right)
274 {
275     return static_cast<VisitGCRootFlags>(static_cast<uint32_t>(left) | static_cast<uint32_t>(right));
276 }
277 
278 template class RootManager<PandaAssemblyLanguageConfig>;
279 
280 }  // namespace panda::mem
281