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
16 #ifndef RUNTIME_MEM_GC_GENERATIONAL_GC_BASE_INL_H
17 #define RUNTIME_MEM_GC_GENERATIONAL_GC_BASE_INL_H
18
19 #include <type_traits>
20 #include "runtime/mem/gc/generational-gc-base.h"
21
22 namespace ark::mem {
23
24 template <class LanguageConfig>
25 template <typename Marker, class... ReferenceCheckPredicate>
MarkStack(Marker * marker,GCMarkingStackType * stack,const GC::MarkPreprocess & markPreprocess,const ReferenceCheckPredicate &...refPred)26 void GenerationalGC<LanguageConfig>::MarkStack(Marker *marker, GCMarkingStackType *stack,
27 const GC::MarkPreprocess &markPreprocess,
28 const ReferenceCheckPredicate &...refPred)
29 {
30 trace::ScopedTrace scopedTrace(__FUNCTION__);
31 // Check that we use correct type for ref_predicate (or not use it at all)
32 static_assert(sizeof...(ReferenceCheckPredicate) == 0 ||
33 (sizeof...(ReferenceCheckPredicate) == 1 &&
34 std::is_constructible_v<ReferenceCheckPredicateT, ReferenceCheckPredicate...>));
35 ASSERT(stack != nullptr);
36 while (!stack->Empty()) {
37 auto *object = this->PopObjectFromStack(stack);
38 ASSERT(marker->IsMarked(object));
39 ValidateObject(nullptr, object);
40 auto *objectClass = object->template NotAtomicClassAddr<BaseClass>();
41 // We need annotation here for the FullMemoryBarrier used in InitializeClassByIdEntrypoint
42 TSAN_ANNOTATE_HAPPENS_AFTER(objectClass);
43 LOG_DEBUG_GC << "Current object: " << GetDebugInfoAboutObject(object);
44
45 ASSERT(!object->IsForwarded());
46 markPreprocess(object, objectClass);
47 static_cast<Marker *>(marker)->MarkInstance(stack, object, objectClass, refPred...);
48 }
49 }
50
51 template <class LanguageConfig>
52 template <typename Marker>
MarkImpl(Marker * marker,GCMarkingStackType * objectsStack,CardTableVisitFlag visitCardTableRoots,const ReferenceCheckPredicateT & refPred,const MemRangeChecker & memRangeChecker,const GC::MarkPreprocess & markPreprocess)53 NO_THREAD_SAFETY_ANALYSIS void GenerationalGC<LanguageConfig>::MarkImpl(Marker *marker,
54 GCMarkingStackType *objectsStack,
55 CardTableVisitFlag visitCardTableRoots,
56 const ReferenceCheckPredicateT &refPred,
57 const MemRangeChecker &memRangeChecker,
58 const GC::MarkPreprocess &markPreprocess)
59 {
60 // concurrent visit class roots
61 this->VisitClassRoots([this, marker, objectsStack](const GCRoot &gcRoot) {
62 if (marker->MarkIfNotMarked(gcRoot.GetObjectHeader())) {
63 ASSERT(gcRoot.GetObjectHeader() != nullptr);
64 objectsStack->PushToStack(RootType::ROOT_CLASS, gcRoot.GetObjectHeader());
65 } else {
66 LOG_DEBUG_GC << "Skip root: " << gcRoot.GetObjectHeader();
67 }
68 });
69 MarkStack(marker, objectsStack, markPreprocess, refPred);
70 {
71 ScopedTiming t1("VisitInternalStringTable", *this->GetTiming());
72 auto visitor = [marker, objectsStack](ObjectHeader *str) {
73 if (marker->MarkIfNotMarked(str)) {
74 ASSERT(str != nullptr);
75 objectsStack->PushToStack(RootType::STRING_TABLE, str);
76 }
77 };
78 this->GetPandaVm()->VisitStringTable(visitor, VisitGCRootFlags::ACCESS_ROOT_ALL |
79 VisitGCRootFlags::START_RECORDING_NEW_ROOT);
80 }
81 MarkStack(marker, objectsStack, markPreprocess, refPred);
82
83 // concurrent visit card table
84 if (visitCardTableRoots == CardTableVisitFlag::VISIT_ENABLED) {
85 this->VisitCardTableConcurrent(marker, objectsStack, refPred, memRangeChecker, markPreprocess);
86 }
87 }
88
89 template <class LanguageConfig>
90 template <typename Marker>
VisitCardTableConcurrent(Marker * marker,GCMarkingStackType * objectsStack,const ReferenceCheckPredicateT & refPred,const MemRangeChecker & memRangeChecker,const GC::MarkPreprocess & markPreprocess)91 void GenerationalGC<LanguageConfig>::VisitCardTableConcurrent(Marker *marker, GCMarkingStackType *objectsStack,
92 const ReferenceCheckPredicateT &refPred,
93 const MemRangeChecker &memRangeChecker,
94 const GC::MarkPreprocess &markPreprocess)
95 {
96 GCRootVisitor gcMarkRoots = [this, marker, objectsStack, &refPred](const GCRoot &gcRoot) {
97 ObjectHeader *fromObject = gcRoot.GetFromObjectHeader();
98 if (UNLIKELY(fromObject != nullptr) &&
99 this->IsReference(fromObject->ClassAddr<BaseClass>(), fromObject, refPred)) {
100 LOG_DEBUG_GC << "Add reference: " << GetDebugInfoAboutObject(fromObject) << " to stack";
101 marker->Mark(fromObject);
102 this->ProcessReference(objectsStack, fromObject->ClassAddr<BaseClass>(), fromObject,
103 GC::EmptyReferenceProcessPredicate);
104 } else {
105 if (marker->MarkIfNotMarked(gcRoot.GetObjectHeader())) {
106 objectsStack->PushToStack(gcRoot.GetType(), gcRoot.GetObjectHeader());
107 }
108 }
109 };
110
111 auto allocator = this->GetObjectAllocator();
112 MemRangeChecker rangeChecker = [&memRangeChecker](MemRange &memRange) -> bool { return memRangeChecker(memRange); };
113 ObjectChecker tenuredObjectChecker = [&allocator](const ObjectHeader *objectHeader) -> bool {
114 return !allocator->IsObjectInYoungSpace(objectHeader);
115 };
116 ObjectChecker fromObjectChecker = [marker](const ObjectHeader *objectHeader) -> bool {
117 return marker->IsMarked(objectHeader);
118 };
119 this->VisitCardTableRoots(this->GetCardTable(), gcMarkRoots, rangeChecker, tenuredObjectChecker, fromObjectChecker,
120 CardTableProcessedFlag::VISIT_MARKED | CardTableProcessedFlag::VISIT_PROCESSED |
121 CardTableProcessedFlag::SET_PROCESSED);
122 MarkStack(marker, objectsStack, markPreprocess, refPred);
123 }
124
125 } // namespace ark::mem
126 #endif // RUNTIME_MEM_GC_GENERATIONAL_GC_BASE_INL_H
127