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 "runtime/mem/gc/generational-gc-base.h"
20
21 namespace panda::mem {
22
23 template <class LanguageConfig>
24 template <typename Marker>
MarkStack(Marker * marker,GCMarkingStackType * stack,const ReferenceCheckPredicateT & ref_pred,const GC::MarkPredicate & markPredicate)25 void GenerationalGC<LanguageConfig>::MarkStack(Marker *marker, GCMarkingStackType *stack,
26 const ReferenceCheckPredicateT &ref_pred,
27 const GC::MarkPredicate &markPredicate)
28 {
29 auto pred = [stack]() { return !stack->Empty(); };
30 MarkStackCond(marker, stack, pred, ref_pred, markPredicate);
31 }
32
33 template <class LanguageConfig>
34 template <typename Marker>
MarkStackCond(Marker * marker,GCMarkingStackType * stack,const ConcurrentMarkPredicateT & pred,const ReferenceCheckPredicateT & ref_pred,const GC::MarkPredicate & markPredicate)35 void GenerationalGC<LanguageConfig>::MarkStackCond(Marker *marker, GCMarkingStackType *stack,
36 const ConcurrentMarkPredicateT &pred,
37 const ReferenceCheckPredicateT &ref_pred,
38 const GC::MarkPredicate &markPredicate)
39 {
40 trace::ScopedTrace scoped_trace(__FUNCTION__);
41 ASSERT(stack != nullptr);
42 while (pred()) {
43 auto *object = this->PopObjectFromStack(stack);
44 ValidateObject(nullptr, object);
45 auto *object_class = object->template ClassAddr<BaseClass>();
46 // We need annotation here for the FullMemoryBarrier used in InitializeClassByIdEntrypoint
47 TSAN_ANNOTATE_HAPPENS_AFTER(object_class);
48 LOG_DEBUG_GC << "Current object: " << GetDebugInfoAboutObject(object);
49
50 ASSERT(!object->IsForwarded());
51 if (markPredicate(object)) {
52 static_cast<Marker *>(marker)->MarkInstance(stack, ref_pred, object, object_class);
53 }
54 }
55 }
56
57 template <class LanguageConfig>
58 template <typename Marker>
ConcurrentMark(Marker * marker,GCMarkingStackType * objects_stack,CardTableVisitFlag visit_card_table_roots,const ConcurrentMarkPredicateT & pred,const ReferenceCheckPredicateT & ref_pred,const MemRangeChecker & mem_range_checker)59 NO_THREAD_SAFETY_ANALYSIS void GenerationalGC<LanguageConfig>::ConcurrentMark(Marker *marker,
60 GCMarkingStackType *objects_stack,
61 CardTableVisitFlag visit_card_table_roots,
62 const ConcurrentMarkPredicateT &pred,
63 const ReferenceCheckPredicateT &ref_pred,
64 const MemRangeChecker &mem_range_checker)
65 {
66 GCScope<TRACE_TIMING_PHASE> scoped_func(__FUNCTION__, this, GCPhase::GC_PHASE_MARK);
67 ConcurrentScope concurrent_scope(this);
68 MarkImpl(marker, objects_stack, visit_card_table_roots, pred, ref_pred, mem_range_checker);
69 }
70
71 template <class LanguageConfig>
72 template <typename Marker>
OnPauseMark(Marker * marker,GCMarkingStackType * objects_stack,CardTableVisitFlag visit_card_table_roots,const ConcurrentMarkPredicateT & pred,const ReferenceCheckPredicateT & ref_pred,const MemRangeChecker & mem_range_checker)73 NO_THREAD_SAFETY_ANALYSIS void GenerationalGC<LanguageConfig>::OnPauseMark(Marker *marker,
74 GCMarkingStackType *objects_stack,
75 CardTableVisitFlag visit_card_table_roots,
76 const ConcurrentMarkPredicateT &pred,
77 const ReferenceCheckPredicateT &ref_pred,
78 const MemRangeChecker &mem_range_checker)
79 {
80 GCScope<TRACE_TIMING_PHASE> scope(__FUNCTION__, this, GCPhase::GC_PHASE_MARK);
81 MarkImpl(marker, objects_stack, visit_card_table_roots, pred, ref_pred, mem_range_checker);
82 }
83
84 template <class LanguageConfig>
85 template <typename Marker>
MarkImpl(Marker * marker,GCMarkingStackType * objects_stack,CardTableVisitFlag visit_card_table_roots,const ConcurrentMarkPredicateT & pred,const ReferenceCheckPredicateT & ref_pred,const MemRangeChecker & mem_range_checker)86 NO_THREAD_SAFETY_ANALYSIS void GenerationalGC<LanguageConfig>::MarkImpl(Marker *marker,
87 GCMarkingStackType *objects_stack,
88 CardTableVisitFlag visit_card_table_roots,
89 const ConcurrentMarkPredicateT &pred,
90 const ReferenceCheckPredicateT &ref_pred,
91 const MemRangeChecker &mem_range_checker)
92 {
93 // concurrent visit class roots
94 this->VisitClassRoots([this, marker, objects_stack](const GCRoot &gc_root) {
95 if (marker->MarkIfNotMarked(gc_root.GetObjectHeader())) {
96 ASSERT(gc_root.GetObjectHeader() != nullptr);
97 objects_stack->PushToStack(RootType::ROOT_CLASS, gc_root.GetObjectHeader());
98 } else {
99 LOG_DEBUG_GC << "Skip root: " << gc_root.GetObjectHeader();
100 }
101 });
102 MarkStackCond(marker, objects_stack, pred, ref_pred, GC::EmptyReferenceProcessPredicate);
103 {
104 ScopedTiming t1("VisitInternalStringTable", *this->GetTiming());
105 this->GetPandaVm()->VisitStringTable(
106 [marker, objects_stack](ObjectHeader *str) {
107 if (marker->MarkIfNotMarked(str)) {
108 ASSERT(str != nullptr);
109 objects_stack->PushToStack(RootType::STRING_TABLE, str);
110 }
111 },
112 VisitGCRootFlags::ACCESS_ROOT_ALL | VisitGCRootFlags::START_RECORDING_NEW_ROOT);
113 }
114 MarkStackCond(marker, objects_stack, pred, ref_pred, GC::EmptyReferenceProcessPredicate);
115
116 // concurrent visit card table
117 if (visit_card_table_roots == CardTableVisitFlag::VISIT_ENABLED) {
118 GCRootVisitor gc_mark_roots = [this, marker, objects_stack, &ref_pred](const GCRoot &gc_root) {
119 ObjectHeader *from_object = gc_root.GetFromObjectHeader();
120 if (UNLIKELY(from_object != nullptr) &&
121 this->IsReference(from_object->ClassAddr<BaseClass>(), from_object, ref_pred)) {
122 LOG_DEBUG_GC << "Add reference: " << GetDebugInfoAboutObject(from_object) << " to stack";
123 marker->Mark(from_object);
124 this->ProcessReference(objects_stack, from_object->ClassAddr<BaseClass>(), from_object,
125 GC::EmptyReferenceProcessPredicate);
126 } else {
127 objects_stack->PushToStack(gc_root.GetType(), gc_root.GetObjectHeader());
128 marker->Mark(gc_root.GetObjectHeader());
129 }
130 };
131
132 auto allocator = this->GetObjectAllocator();
133 MemRangeChecker range_checker = [&mem_range_checker](MemRange &mem_range) -> bool {
134 return mem_range_checker(mem_range);
135 };
136 ObjectChecker tenured_object_checker = [&allocator](const ObjectHeader *object_header) -> bool {
137 return !allocator->IsAddressInYoungSpace(ToUintPtr(object_header));
138 };
139 ObjectChecker from_object_checker = [marker](const ObjectHeader *object_header) -> bool {
140 return marker->IsMarked(object_header);
141 };
142 this->VisitCardTableRoots(this->GetCardTable(), gc_mark_roots, range_checker, tenured_object_checker,
143 from_object_checker,
144 CardTableProcessedFlag::VISIT_MARKED | CardTableProcessedFlag::VISIT_PROCESSED |
145 CardTableProcessedFlag::SET_PROCESSED);
146 MarkStackCond(marker, objects_stack, pred, ref_pred, GC::EmptyReferenceProcessPredicate);
147 }
148 }
149
150 } // namespace panda::mem
151 #endif // RUNTIME_MEM_GC_GENERATIONAL_GC_BASE_INL_H
152