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
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 panda::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 this->GetPandaVm()->VisitStringTable(
73 [marker, objectsStack](ObjectHeader *str) {
74 if (marker->MarkIfNotMarked(str)) {
75 ASSERT(str != nullptr);
76 objectsStack->PushToStack(RootType::STRING_TABLE, str);
77 }
78 },
79 VisitGCRootFlags::ACCESS_ROOT_ALL | 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 GCRootVisitor gcMarkRoots = [this, marker, objectsStack, &refPred](const GCRoot &gcRoot) {
86 ObjectHeader *fromObject = gcRoot.GetFromObjectHeader();
87 if (UNLIKELY(fromObject != nullptr) &&
88 this->IsReference(fromObject->ClassAddr<BaseClass>(), fromObject, refPred)) {
89 LOG_DEBUG_GC << "Add reference: " << GetDebugInfoAboutObject(fromObject) << " to stack";
90 marker->Mark(fromObject);
91 this->ProcessReference(objectsStack, fromObject->ClassAddr<BaseClass>(), fromObject,
92 GC::EmptyReferenceProcessPredicate);
93 } else {
94 if (marker->MarkIfNotMarked(gcRoot.GetObjectHeader())) {
95 objectsStack->PushToStack(gcRoot.GetType(), gcRoot.GetObjectHeader());
96 }
97 }
98 };
99
100 auto allocator = this->GetObjectAllocator();
101 MemRangeChecker rangeChecker = [&memRangeChecker](MemRange &memRange) -> bool {
102 return memRangeChecker(memRange);
103 };
104 ObjectChecker tenuredObjectChecker = [&allocator](const ObjectHeader *objectHeader) -> bool {
105 return !allocator->IsObjectInYoungSpace(objectHeader);
106 };
107 ObjectChecker fromObjectChecker = [marker](const ObjectHeader *objectHeader) -> bool {
108 return marker->IsMarked(objectHeader);
109 };
110 this->VisitCardTableRoots(this->GetCardTable(), gcMarkRoots, rangeChecker, tenuredObjectChecker,
111 fromObjectChecker,
112 CardTableProcessedFlag::VISIT_MARKED | CardTableProcessedFlag::VISIT_PROCESSED |
113 CardTableProcessedFlag::SET_PROCESSED);
114 MarkStack(marker, objectsStack, markPreprocess, refPred);
115 }
116 }
117
118 } // namespace panda::mem
119 #endif // RUNTIME_MEM_GC_GENERATIONAL_GC_BASE_INL_H
120