1 /**
2 * Copyright (c) 2021-2025 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/generational-gc-base.h"
17 #include "runtime/include/runtime.h"
18 #include "runtime/include/runtime_notification.h"
19 #include "runtime/include/panda_vm.h"
20
21 namespace ark::mem {
22
23 template <class LanguageConfig>
ShouldRunTenuredGC(const GCTask & task)24 bool GenerationalGC<LanguageConfig>::ShouldRunTenuredGC(const GCTask &task)
25 {
26 return this->IsOnPygoteFork() || task.reason == GCTaskCause::OOM_CAUSE ||
27 task.reason == GCTaskCause::EXPLICIT_CAUSE || task.reason == GCTaskCause::HEAP_USAGE_THRESHOLD_CAUSE ||
28 task.reason == GCTaskCause::STARTUP_COMPLETE_CAUSE;
29 }
30
31 template <class LanguageConfig>
Dump()32 PandaString GenerationalGC<LanguageConfig>::MemStats::Dump()
33 {
34 PandaStringStream statistic;
35 statistic << "Young freed " << youngFreeObjectCount_ << " objects ("
36 << helpers::MemoryConverter(youngFreeObjectSize_) << ") Young moved " << youngMoveObjectCount_
37 << " objects, " << youngMoveObjectSize_ << " bytes (" << helpers::MemoryConverter(youngMoveObjectSize_)
38 << ")";
39 if (tenuredFreeObjectSize_ > 0U) {
40 statistic << " Tenured freed " << tenuredFreeObjectSize_ << "("
41 << helpers::MemoryConverter(tenuredFreeObjectSize_) << ")";
42 }
43 return statistic.str();
44 }
45
46 template <class LanguageConfig>
UpdateMemStats(size_t bytesInHeapBefore,bool updateTenuredStats,bool recordAllocationForMovedObjects)47 void GenerationalGC<LanguageConfig>::UpdateMemStats(size_t bytesInHeapBefore, bool updateTenuredStats,
48 bool recordAllocationForMovedObjects)
49 {
50 size_t youngMoveSize = this->memStats_.GetSizeMovedYoung();
51 size_t youngMoveCount = this->memStats_.GetCountMovedYoung();
52 size_t youngDeleteSize = this->memStats_.GetSizeFreedYoung();
53 size_t youngDeleteCount = this->memStats_.GetCountFreedYoung();
54 size_t tenuredMoveSize = updateTenuredStats ? this->memStats_.GetSizeMovedTenured() : 0;
55 size_t tenuredMoveCount = updateTenuredStats ? this->memStats_.GetCountMovedTenured() : 0;
56 size_t tenuredDeleteSize = updateTenuredStats ? this->memStats_.GetSizeFreedTenured() : 0;
57 size_t tenuredDeleteCount = updateTenuredStats ? this->memStats_.GetCountFreedTenured() : 0;
58
59 auto *vmMemStats = this->GetPandaVm()->GetMemStats();
60 GCInstanceStats *gcStats = this->GetStats();
61
62 if (recordAllocationForMovedObjects) {
63 vmMemStats->RecordAllocateObjects(youngMoveCount + tenuredMoveCount, youngMoveSize + tenuredMoveSize,
64 SpaceType::SPACE_TYPE_OBJECT);
65 }
66 if (youngMoveSize > 0) {
67 gcStats->AddMemoryValue(youngMoveSize, MemoryTypeStats::MOVED_BYTES);
68 gcStats->AddObjectsValue(youngMoveCount, ObjectTypeStats::MOVED_OBJECTS);
69 vmMemStats->RecordYoungMovedObjects(youngMoveCount, youngMoveSize, SpaceType::SPACE_TYPE_OBJECT);
70 }
71 if (youngDeleteSize > 0) {
72 gcStats->AddMemoryValue(youngDeleteSize, MemoryTypeStats::YOUNG_FREED_BYTES);
73 gcStats->AddObjectsValue(youngDeleteCount, ObjectTypeStats::YOUNG_FREED_OBJECTS);
74 }
75
76 if (bytesInHeapBefore > 0) {
77 gcStats->AddCopiedRatioValue(static_cast<double>(youngMoveSize + tenuredMoveSize) / bytesInHeapBefore);
78 }
79
80 if (tenuredMoveSize > 0) {
81 gcStats->AddMemoryValue(tenuredMoveSize, MemoryTypeStats::MOVED_BYTES);
82 gcStats->AddObjectsValue(tenuredMoveCount, ObjectTypeStats::MOVED_OBJECTS);
83 vmMemStats->RecordTenuredMovedObjects(tenuredMoveCount, tenuredMoveSize, SpaceType::SPACE_TYPE_OBJECT);
84 }
85 if (tenuredDeleteSize > 0) {
86 gcStats->AddMemoryValue(tenuredDeleteSize, MemoryTypeStats::ALL_FREED_BYTES);
87 gcStats->AddObjectsValue(tenuredDeleteCount, ObjectTypeStats::ALL_FREED_OBJECTS);
88 }
89 vmMemStats->RecordFreeObjects(youngDeleteCount + tenuredDeleteCount, youngDeleteSize + tenuredDeleteSize,
90 SpaceType::SPACE_TYPE_OBJECT);
91 }
92
93 template <class LanguageConfig>
CreateCardTable(InternalAllocatorPtr internalAllocatorPtr,uintptr_t minAddress,size_t size)94 void GenerationalGC<LanguageConfig>::CreateCardTable(InternalAllocatorPtr internalAllocatorPtr, uintptr_t minAddress,
95 size_t size)
96 {
97 cardTable_ = MakePandaUnique<CardTable>(internalAllocatorPtr, minAddress, size);
98 ASSERT(cardTable_.get() != nullptr);
99 cardTable_->Initialize();
100 }
101
102 template <class LanguageConfig>
Trigger(PandaUniquePtr<GCTask> task)103 bool GenerationalGC<LanguageConfig>::Trigger(PandaUniquePtr<GCTask> task)
104 {
105 // Check current heap size.
106 // Collect Young gen.
107 // If threshold for tenured gen - collect tenured gen.
108 // NOTE(dtrubenkov): change for concurrent mode
109 return this->AddGCTask(true, std::move(task));
110 }
111
112 TEMPLATE_CLASS_LANGUAGE_CONFIG(GenerationalGC);
113 } // namespace ark::mem
114