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