• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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/mem_stats.h"
17 
18 #include "libpandabase/utils/utf.h"
19 #include "runtime/include/class.h"
20 #include "runtime/include/runtime.h"
21 #include "runtime/mem/mem_stats_additional_info.h"
22 #include "runtime/mem/mem_stats_default.h"
23 #include "runtime/mem/object_helpers.h"
24 
25 namespace ark::mem {
26 
27 template <typename T>
RecordAllocateObject(size_t size,SpaceType typeMem)28 void MemStats<T>::RecordAllocateObject(size_t size, SpaceType typeMem)
29 {
30     RecordAllocateObjects(1, size, typeMem);
31 }
32 
33 template <typename T>
RecordAllocateObjects(size_t totalObjectNum,size_t totalObjectSize,SpaceType typeMem)34 void MemStats<T>::RecordAllocateObjects(size_t totalObjectNum, size_t totalObjectSize, SpaceType typeMem)
35 {
36     ASSERT(IsHeapSpace(typeMem));
37     RecordAllocate(totalObjectSize, typeMem);
38     if (typeMem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
39         // Atomic with acq_rel order reason: data race with humongous_objects_allocated_ with dependecies on reads after
40         // the load and on writes before the store
41         humongousObjectsAllocated_.fetch_add(totalObjectNum, std::memory_order_acq_rel);
42     } else {
43         // Atomic with acq_rel order reason: data race with objects_allocated_ with dependecies on reads after the load
44         // and on writes before the store
45         objectsAllocated_.fetch_add(totalObjectNum, std::memory_order_acq_rel);
46     }
47 }
48 
49 template <typename T>
RecordYoungMovedObjects(size_t youngObjectNum,size_t size,SpaceType typeMem)50 void MemStats<T>::RecordYoungMovedObjects(size_t youngObjectNum, size_t size, SpaceType typeMem)
51 {
52     ASSERT(IsHeapSpace(typeMem));
53     RecordMoved(size, typeMem);
54     // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
55     ASSERT(typeMem != SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
56     // Atomic with acq_rel order reason: data race with last_young_objects_moved_bytes_ with dependecies on reads after
57     // the load and on writes before the store
58     lastYoungObjectsMovedBytes_.fetch_add(size, std::memory_order_acq_rel);
59     // Atomic with acq_rel order reason: data race with objects_allocated_ with dependecies on reads after the load and
60     // on writes before the store
61     [[maybe_unused]] uint64_t oldVal = objectsAllocated_.fetch_sub(youngObjectNum, std::memory_order_acq_rel);
62     ASSERT(oldVal >= youngObjectNum);
63 }
64 
65 template <typename T>
RecordTenuredMovedObjects(size_t tenuredObjectNum,size_t size,SpaceType typeMem)66 void MemStats<T>::RecordTenuredMovedObjects(size_t tenuredObjectNum, size_t size, SpaceType typeMem)
67 {
68     ASSERT(IsHeapSpace(typeMem));
69     RecordMoved(size, typeMem);
70     // We can't move SPACE_TYPE_HUMONGOUS_OBJECT
71     ASSERT(typeMem != SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
72     // Atomic with acq_rel order reason: data race with objects_allocated_ with dependecies on reads after the load and
73     // on writes before the store
74     [[maybe_unused]] uint64_t oldVal = objectsAllocated_.fetch_sub(tenuredObjectNum, std::memory_order_acq_rel);
75     ASSERT(oldVal >= tenuredObjectNum);
76 }
77 
78 template <typename T>
RecordFreeObject(size_t objectSize,SpaceType typeMem)79 void MemStats<T>::RecordFreeObject(size_t objectSize, SpaceType typeMem)
80 {
81     RecordFreeObjects(1, objectSize, typeMem);
82 }
83 
84 template <typename T>
RecordFreeObjects(size_t totalObjectNum,size_t totalObjectSize,SpaceType typeMem)85 void MemStats<T>::RecordFreeObjects(size_t totalObjectNum, size_t totalObjectSize, SpaceType typeMem)
86 {
87     ASSERT(IsHeapSpace(typeMem));
88     RecordFree(totalObjectSize, typeMem);
89     if (typeMem == SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT) {
90         // Atomic with acq_rel order reason: data race with humongous_objects_freed_ with dependecies on reads after the
91         // load and on writes before the store
92         humongousObjectsFreed_.fetch_add(totalObjectNum, std::memory_order_acq_rel);
93     } else {
94         // Atomic with acq_rel order reason: data race with objects_freed_ with dependecies on reads after the load and
95         // on writes before the store
96         objectsFreed_.fetch_add(totalObjectNum, std::memory_order_acq_rel);
97     }
98 }
99 
100 template <typename T>
GetStatistics()101 PandaString MemStats<T>::GetStatistics()
102 {
103     PandaStringStream statistic;
104     statistic << "memory statistics:" << std::endl;
105     statistic << "heap: allocated - " << GetAllocatedHeap() << ", freed - " << GetFreedHeap() << std::endl;
106     statistic << "raw memory: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_INTERNAL) << ", freed - "
107               << GetFreed(SpaceType::SPACE_TYPE_INTERNAL) << std::endl;
108     statistic << "compiler: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_CODE) << std::endl;
109     statistic << "ArenaAllocator: allocated - " << GetAllocated(SpaceType::SPACE_TYPE_COMPILER) << std::endl;
110     statistic << "total footprint now - " << GetTotalFootprint() << std::endl;
111     statistic << "total allocated object - " << GetTotalObjectsAllocated() << std::endl;
112     auto additionalStatistics = static_cast<T *>(this)->GetAdditionalStatistics();
113     return statistic.str() + additionalStatistics;
114 }
115 
116 template <typename T>
GetTotalObjectsAllocated() const117 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsAllocated() const
118 {
119     // Atomic with acquire order reason: data race with objects_allocated_ with dependecies on reads after the load
120     // which should become visible
121     return objectsAllocated_.load(std::memory_order_acquire);
122 }
123 
124 template <typename T>
GetTotalObjectsFreed() const125 [[nodiscard]] uint64_t MemStats<T>::GetTotalObjectsFreed() const
126 {
127     // Atomic with acquire order reason: data race with objects_freed_ with dependecies on reads after the load which
128     // should become visible
129     return objectsFreed_.load(std::memory_order_acquire);
130 }
131 
132 template <typename T>
GetTotalRegularObjectsAllocated() const133 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsAllocated() const
134 {
135     return GetTotalObjectsAllocated() - GetTotalHumongousObjectsAllocated();
136 }
137 
138 template <typename T>
GetTotalRegularObjectsFreed() const139 [[nodiscard]] uint64_t MemStats<T>::GetTotalRegularObjectsFreed() const
140 {
141     return GetTotalObjectsFreed() - GetTotalHumongousObjectsFreed();
142 }
143 
144 template <typename T>
GetTotalHumongousObjectsAllocated() const145 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsAllocated() const
146 {
147     // Atomic with acquire order reason: data race with humongous_objects_allocated_ with dependecies on reads after the
148     // load which should become visible
149     return humongousObjectsAllocated_.load(std::memory_order_acquire);
150 }
151 
152 template <typename T>
GetTotalHumongousObjectsFreed() const153 [[nodiscard]] uint64_t MemStats<T>::GetTotalHumongousObjectsFreed() const
154 {
155     // Atomic with acquire order reason: data race with humongous_objects_freed_ with dependecies on reads after the
156     // load which should become visible
157     return humongousObjectsFreed_.load(std::memory_order_acquire);
158 }
159 
160 template <typename T>
GetObjectsCountAlive() const161 [[nodiscard]] uint64_t MemStats<T>::GetObjectsCountAlive() const
162 {
163     return GetTotalObjectsAllocated() - GetTotalObjectsFreed();
164 }
165 
166 template <typename T>
GetRegularObjectsCountAlive() const167 [[nodiscard]] uint64_t MemStats<T>::GetRegularObjectsCountAlive() const
168 {
169     return GetTotalRegularObjectsAllocated() - GetTotalRegularObjectsFreed();
170 }
171 
172 template <typename T>
GetHumonguousObjectsCountAlive() const173 [[nodiscard]] uint64_t MemStats<T>::GetHumonguousObjectsCountAlive() const
174 {
175     return GetTotalHumongousObjectsAllocated() - GetTotalHumongousObjectsFreed();
176 }
177 
178 template <typename T>
GetLastYoungObjectsMovedBytes() const179 [[nodiscard]] uint64_t MemStats<T>::GetLastYoungObjectsMovedBytes() const
180 {
181     // Atomic with acquire order reason: data race with last_young_objects_moved_bytes_ with dependecies on reads after
182     // the load which should become visible
183     return lastYoungObjectsMovedBytes_.load(std::memory_order_acquire);
184 }
185 
186 template class MemStats<MemStatsDefault>;
187 template class MemStats<MemStatsAdditionalInfo>;
188 }  // namespace ark::mem
189