• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "runtime/mem/gc/g1/g1-gc.h"
17 #include "runtime/include/panda_vm.h"
18 
19 namespace panda::mem {
20 
PreStoreInBuffG1(void * object_header)21 void PreStoreInBuffG1([[maybe_unused]] void *object_header) {}
22 
23 template <class LanguageConfig>
G1GC(ObjectAllocatorBase * object_allocator,const GCSettings & settings)24 G1GC<LanguageConfig>::G1GC(ObjectAllocatorBase *object_allocator, const GCSettings &settings)
25     : GenerationalGC<LanguageConfig>(object_allocator, settings)
26 {
27     post_queue_func_ = [this](const void *from, const void *to) {
28         // No need to keep remsets for young->young
29         if (!(Region::AddrToRegion(from)->IsEden() && Region::AddrToRegion(to)->IsEden())) {
30             os::memory::LockHolder lock(this->queue_lock_);
31             LOG_DEBUG_GC << "post queue add ref: " << std::hex << from << " -> " << to;
32             this->updated_refs_queue_.emplace_back(from, to);
33         }
34     };
35 }
36 
37 template <class LanguageConfig>
InitGCBits(panda::ObjectHeader * obj_header)38 void G1GC<LanguageConfig>::InitGCBits(panda::ObjectHeader *obj_header)
39 {
40     if (UNLIKELY(this->GetGCPhase() == GCPhase::GC_PHASE_SWEEP) && (!IsInCollectibleSet(obj_header))) {
41         obj_header->SetMarkedForGC();
42     } else {
43         obj_header->SetUnMarkedForGC();
44     }
45     LOG_DEBUG_GC << "Init gc bits for object: " << std::hex << obj_header << " bit: " << obj_header->IsMarkedForGC()
46                  << ", is marked = " << IsMarked(obj_header);
47 }
48 
49 template <class LanguageConfig>
PreStartupImp()50 void G1GC<LanguageConfig>::PreStartupImp()
51 {
52     LOG(FATAL, GC) << "Not implemented";
53 }
54 
55 template <class LanguageConfig>
Trigger()56 void G1GC<LanguageConfig>::Trigger()
57 {
58     auto task = MakePandaUnique<GCTask>(GCTaskCause::HEAP_USAGE_THRESHOLD_CAUSE, time::GetCurrentTimeInNanos());
59     this->AddGCTask(true, std::move(task), true);
60 }
61 
62 template <class LanguageConfig>
RunPhasesImpl(panda::GCTask const & task)63 void G1GC<LanguageConfig>::RunPhasesImpl([[maybe_unused]] panda::GCTask const &task)
64 {
65     LOG(INFO, GC) << "GenGC start";
66     LOG_DEBUG_GC << "Footprint before GC: " << this->GetPandaVm()->GetMemStats()->GetFootprintHeap();
67     GCScopedPauseStats scoped_pause_stats(this->GetPandaVm()->GetGCStats());
68     LOG_DEBUG_GC << "Young range: " << this->GetObjectAllocator()->GetYoungSpaceMemRange();
69     uint64_t young_total_time;
70     this->GetTiming()->Reset();
71     {
72         ScopedTiming t("Generational GC", *this->GetTiming());
73         this->mem_stats_.Reset();
74         {
75             time::Timer timer(&young_total_time, true);
76             this->GetPandaVm()->GetMemStats()->RecordGCPauseStart();
77             this->BindBitmaps(false);
78             this->GetPandaVm()->GetMemStats()->RecordGCPhaseEnd();
79         }
80         if (young_total_time > 0) {
81             this->GetStats()->AddTimeValue(young_total_time, TimeTypeStats::YOUNG_TOTAL_TIME);
82         }
83         // we trigger a full gc at first pygote fork
84         if (this->ShouldRunTenuredGC(task) || this->IsOnPygoteFork() || task.reason_ == GCTaskCause::OOM_CAUSE ||
85             task.reason_ == GCTaskCause::EXPLICIT_CAUSE) {
86             this->BindBitmaps(true);  // clear pygote live bitmaps, we will rebuild it
87         }
88     }
89     LOG_DEBUG_GC << "Footprint after GC: " << this->GetPandaVm()->GetMemStats()->GetFootprintHeap();
90     LOG(INFO, GC) << this->mem_stats_.Dump();
91     LOG(INFO, GC) << this->GetTiming()->Dump();
92     this->GetTiming()->Reset();  // Clear records.
93 }
94 
95 template <class LanguageConfig>
InitializeImpl()96 void G1GC<LanguageConfig>::InitializeImpl()
97 {
98     // GC saved the PandaVM instance, so we get allocator from the PandaVM.
99     InternalAllocatorPtr allocator = this->GetInternalAllocator();
100     card_table_ = MakePandaUnique<CardTable>(allocator, PoolManager::GetMmapMemPool()->GetMinObjectAddress(),
101                                              PoolManager::GetMmapMemPool()->GetTotalObjectSize());
102     card_table_->Initialize();
103     auto barrier_set = allocator->New<GCG1BarrierSet>(allocator, &concurrent_marking_flag_, PreStoreInBuffG1,
104                                                       PoolManager::GetMmapMemPool()->GetAddressOfMinObjectAddress(),
105                                                       reinterpret_cast<uint8_t *>(*card_table_->begin()),
106                                                       CardTable::GetCardBits(), CardTable::GetCardDirtyValue(),
107                                                       post_queue_func_, this->GetG1ObjectAllocator()->GetRegionSize());
108     ASSERT(barrier_set != nullptr);
109     this->SetGCBarrierSet(barrier_set);
110     LOG_DEBUG_GC << "GenGC initialized";
111 }
112 
113 template <class LanguageConfig>
MarkObject(panda::ObjectHeader * object)114 void G1GC<LanguageConfig>::MarkObject([[maybe_unused]] panda::ObjectHeader *object)
115 {
116     LOG(FATAL, GC) << "Not implemented";
117 }
118 
119 template <class LanguageConfig>
InitGCBitsForAllocationInTLAB(panda::ObjectHeader * object)120 void G1GC<LanguageConfig>::InitGCBitsForAllocationInTLAB([[maybe_unused]] panda::ObjectHeader *object)
121 {
122     LOG(FATAL, GC) << "Not implemented";
123 }
124 
125 template <class LanguageConfig>
IsMarked(panda::ObjectHeader const * object) const126 bool G1GC<LanguageConfig>::IsMarked([[maybe_unused]] panda::ObjectHeader const *object) const
127 {
128     LOG(FATAL, GC) << "Not implemented";
129     return true;
130 }
131 
132 template <class LanguageConfig>
MarkReferences(PandaStackTL<ObjectHeader * > * references,GCPhase gc_phase)133 void G1GC<LanguageConfig>::MarkReferences([[maybe_unused]] PandaStackTL<ObjectHeader *> *references,
134                                           [[maybe_unused]] GCPhase gc_phase)
135 {
136     LOG(FATAL, GC) << "Not implemented";
137 }
138 
139 template <class LanguageConfig>
UnMarkObject(panda::ObjectHeader * object)140 void G1GC<LanguageConfig>::UnMarkObject([[maybe_unused]] panda::ObjectHeader *object)
141 {
142     LOG(FATAL, GC) << "Not implemented";
143 }
144 
145 template <class LanguageConfig>
MarkObjectIfNotMarked(panda::ObjectHeader * object)146 bool G1GC<LanguageConfig>::MarkObjectIfNotMarked([[maybe_unused]] panda::ObjectHeader *object)
147 {
148     LOG(FATAL, GC) << "Not implemented";
149     return true;
150 }
151 
152 template <class LanguageConfig>
IsInCollectibleSet(ObjectHeader * obj_header) const153 bool G1GC<LanguageConfig>::IsInCollectibleSet(ObjectHeader *obj_header) const
154 {
155     return !this->GetObjectAllocator()->IsAddressInYoungSpace(ToUintPtr(obj_header));
156 }
157 
158 template class G1GC<PandaAssemblyLanguageConfig>;
159 
160 }  // namespace panda::mem
161