• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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