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