• 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 #ifndef PANDA_MEM_HEAP_MANAGER_H
16 #define PANDA_MEM_HEAP_MANAGER_H
17 
18 #include <cstddef>
19 #include <memory>
20 
21 #include "libpandabase/utils/logger.h"
22 #include "libpandabase/macros.h"
23 #include "runtime/include/class.h"
24 #include "runtime/include/mem/allocator.h"
25 #include "runtime/include/mem/panda_containers.h"
26 #include "runtime/include/object_header.h"
27 #include "runtime/include/thread.h"
28 #include "runtime/mem/frame_allocator-inl.h"
29 #include "runtime/mem/heap_verifier.h"
30 #include "runtime/mem/tlab.h"
31 #include "runtime/mem/gc/heap-space-misc/crossing_map_singleton.h"
32 
33 namespace panda {
34 // Forward declaration
35 class Runtime;
36 class PandaVM;
37 class RuntimeNotificationManager;
38 }  //  namespace panda
39 
40 namespace panda::mem {
41 
42 // Forward declaration
43 class MemoryManager;
44 
45 class HeapManager {
46 public:
47     bool Initialize(GCType gcType, bool singleThreaded, bool useTlab, MemStatsType *memStats,
48                     InternalAllocatorPtr internalAllocator, bool createPygoteSpace);
49 
50     bool Finalize();
51 
52     [[nodiscard]] PANDA_PUBLIC_API ObjectHeader *AllocateObject(
53         BaseClass *cls, size_t size, Alignment align = DEFAULT_ALIGNMENT, ManagedThread *thread = nullptr,
54         ObjectAllocatorBase::ObjMemInitPolicy objInitType = ObjectAllocatorBase::ObjMemInitPolicy::REQUIRE_INIT);
55 
56     template <bool IS_FIRST_CLASS_CLASS = false>
57     [[nodiscard]] ObjectHeader *AllocateNonMovableObject(
58         BaseClass *cls, size_t size, Alignment align = DEFAULT_ALIGNMENT, ManagedThread *thread = nullptr,
59         ObjectAllocatorBase::ObjMemInitPolicy objInitType = ObjectAllocatorBase::ObjMemInitPolicy::REQUIRE_INIT);
60 
61     /**
62      * @brief Allocates memory for ExtFrame, but do not construct it
63      * @param size - size of allocation (ExtFrame) in bytes
64      * @param ext_sz - size of frame extension in bytes
65      * @return pointer to Frame
66      */
67     [[nodiscard]] PANDA_PUBLIC_API Frame *AllocateExtFrame(size_t size, size_t extSz);
68 
69     /**
70      * @brief Frees memory occupied by ExtFrame
71      * @param frame - pointer to Frame
72      * @param ext_sz - size of frame extension in bytes
73      */
74     void PANDA_PUBLIC_API FreeExtFrame(Frame *frame, size_t extSz);
75 
76     CodeAllocator *GetCodeAllocator() const;
77 
78     PANDA_PUBLIC_API InternalAllocatorPtr GetInternalAllocator();
79 
UseTLABForAllocations()80     bool UseTLABForAllocations()
81     {
82         return useTlabForAllocations_;
83     }
84 
85     bool CreateNewTLAB(ManagedThread *thread);
86 
GetTLABMaxAllocSize()87     size_t GetTLABMaxAllocSize()
88     {
89         return UseTLABForAllocations() ? objectAllocator_.AsObjectAllocator()->GetTLABMaxAllocSize() : 0;
90     }
91 
92     /**
93      * Register TLAB information in MemStats during changing TLAB in a thread
94      * or during thread destroying.
95      */
96     void RegisterTLAB(const TLAB *tlab);
97 
98     /**
99      * Prepare the heap before the fork process, The main function is to compact zygote space for fork subprocess
100      *
101      * @param
102      * @return void
103      */
104     void PreZygoteFork();
105 
106     /**
107      *  NOTE :  Not yet implemented
108      *  To implement the getTargetHeapUtilization and nativeSetTargetHeapUtilization,
109      *  I set two functions and a fixed initial value here. They may need to be rewritten
110      */
111     float GetTargetHeapUtilization() const;
112 
113     void SetTargetHeapUtilization(float target);
114 
VerifyHeapReferences()115     size_t VerifyHeapReferences()
116     {
117         trace::ScopedTrace scopedTrace(__FUNCTION__);
118         size_t failCount = 0;
119         HeapObjectVerifier verifier(this, &failCount);
120         objectAllocator_->IterateOverObjects(verifier);
121         return verifier.GetFailCount();
122     }
123 
124     // Returns the maximum amount of memory a program can consume.
GetMaxMemory()125     size_t GetMaxMemory() const
126     {
127         return MemConfig::GetHeapSizeLimit();
128     }
129 
130     // Returns approximate amount of memory currently consumed by an application.
131     PANDA_PUBLIC_API size_t GetTotalMemory() const;
132 
133     // Returns how much free memory we have until we need to grow the heap to perform an allocation.
134     PANDA_PUBLIC_API size_t GetFreeMemory() const;
135 
136     /// Clamp current accessable heap size as maximum heap size
137     void ClampNewMaxHeapSize();
138 
139     // added for VMDebug::countInstancesOfClass and countInstancesOfClasses
140     void CountInstances(const PandaVector<Class *> &classes, bool assignable, uint64_t *counts);
141 
142     using IsObjectFinalizebleFunc = bool (*)(BaseClass *);
143     using RegisterFinalizeReferenceFunc = void (*)(ObjectHeader *, BaseClass *);
144     void SetIsFinalizableFunc(IsObjectFinalizebleFunc func);
145     void SetRegisterFinalizeReferenceFunc(RegisterFinalizeReferenceFunc func);
146 
147     bool IsObjectFinalized(BaseClass *cls);
148     void RegisterFinalizedObject(ObjectHeader *object, BaseClass *cls, bool isObjectFinalizable);
149 
150     void SetPandaVM(PandaVM *vm);
151 
GetPandaVM()152     PandaVM *GetPandaVM() const
153     {
154         return vm_;
155     }
156 
GetGC()157     mem::GC *GetGC() const
158     {
159         return gc_;
160     }
161 
GetNotificationManager()162     RuntimeNotificationManager *GetNotificationManager() const
163     {
164         return notificationManager_;
165     }
166 
GetMemStats()167     MemStatsType *GetMemStats() const
168     {
169         return memStats_;
170     }
171 
IterateOverObjects(const ObjectVisitor & objectVisitor)172     ALWAYS_INLINE void IterateOverObjects(const ObjectVisitor &objectVisitor)
173     {
174         GetObjectAllocator()->IterateOverObjects(objectVisitor);
175     }
176 
PinObject(ObjectHeader * object)177     ALWAYS_INLINE void PinObject(ObjectHeader *object)
178     {
179         GetObjectAllocator().AsObjectAllocator()->PinObject(object);
180     }
181 
UnpinObject(ObjectHeader * object)182     ALWAYS_INLINE void UnpinObject(ObjectHeader *object)
183     {
184         GetObjectAllocator().AsObjectAllocator()->UnpinObject(object);
185     }
186 
IsObjectInYoungSpace(const ObjectHeader * obj)187     ALWAYS_INLINE bool IsObjectInYoungSpace(const ObjectHeader *obj)
188     {
189         return GetObjectAllocator().AsObjectAllocator()->IsObjectInYoungSpace(obj);
190     }
191 
IsObjectInNonMovableSpace(const ObjectHeader * obj)192     ALWAYS_INLINE bool IsObjectInNonMovableSpace(const ObjectHeader *obj)
193     {
194         return GetObjectAllocator().AsObjectAllocator()->IsObjectInNonMovableSpace(obj);
195     }
196 
IsLiveObject(const ObjectHeader * obj)197     ALWAYS_INLINE bool IsLiveObject(const ObjectHeader *obj)
198     {
199         return GetObjectAllocator().AsObjectAllocator()->IsLive(obj);
200     }
201 
ContainObject(const ObjectHeader * obj)202     ALWAYS_INLINE bool ContainObject(const ObjectHeader *obj)
203     {
204         return GetObjectAllocator().AsObjectAllocator()->ContainObject(obj);
205     }
206 
HeapManager()207     HeapManager() : targetUtilization_(DEFAULT_TARGET_UTILIZATION) {}
208 
209     ~HeapManager() = default;
210 
211     NO_COPY_SEMANTIC(HeapManager);
212     NO_MOVE_SEMANTIC(HeapManager);
213 
214 private:
215     template <GCType GC_TYPE, MTModeT MT_MODE = MT_MODE_MULTI>
Initialize(MemStatsType * memStats,bool createPygoteSpace)216     bool Initialize(MemStatsType *memStats, bool createPygoteSpace)
217     {
218         ASSERT(!isInitialized_);
219         isInitialized_ = true;
220 
221         codeAllocator_ = new (std::nothrow) CodeAllocator(memStats);
222         // For now, crossing map is shared by diffrent VMs.
223         if (!CrossingMapSingleton::IsCreated()) {
224             CrossingMapSingleton::Create();
225         }
226         objectAllocator_ =
227             new (std::nothrow) typename AllocConfig<GC_TYPE, MT_MODE>::ObjectAllocatorType(memStats, createPygoteSpace);
228         return (codeAllocator_ != nullptr) && (internalAllocator_ != nullptr) && (objectAllocator_ != nullptr);
229     }
230 
231     /**
232      * Initialize GC bits and also zeroing memory for the whole Object memory
233      * @param cls - class
234      * @param mem - pointer to the ObjectHeader
235      * @return pointer to the ObjectHeader
236      */
237     ObjectHeader *InitObjectHeaderAtMem(BaseClass *cls, void *mem);
238 
239     /// Triggers GC if needed
240     void TriggerGCIfNeeded();
241 
242     void *TryGCAndAlloc(size_t size, Alignment align, ManagedThread *thread,
243                         ObjectAllocatorBase::ObjMemInitPolicy objInitType);
244 
245     void *AllocByTLAB(size_t size, ManagedThread *thread);
246 
247     void *AllocateMemoryForObject(size_t size, Alignment align, ManagedThread *thread,
248                                   ObjectAllocatorBase::ObjMemInitPolicy objInitType);
249 
250     ObjectAllocatorPtr GetObjectAllocator();
251 
252     static constexpr float DEFAULT_TARGET_UTILIZATION = 0.5;
253 
254     bool isInitialized_ = false;
255     bool useRuntimeInternalAllocator_ {true};
256     CodeAllocator *codeAllocator_ = nullptr;
257     InternalAllocatorPtr internalAllocator_ = nullptr;
258     ObjectAllocatorPtr objectAllocator_ = nullptr;
259 
260     bool useTlabForAllocations_ = false;
261 
262     /// StackFrameAllocator is per thread
263     StackFrameAllocator *GetCurrentStackFrameAllocator();
264 
265     friend class ::panda::Runtime;
266 
267     // Needed to extract object allocator created during HeapManager initialization
268     // to pass it to GC creation method;
269     friend class ::panda::mem::MemoryManager;
270 
271     /**
272      * NOTE : Target ideal heap utilization ratio.
273      * To implement the getTargetHeapUtilization and nativeSetTargetHeapUtilization, I set a variable here.
274      * It may need to be initialized, but now I give it a fixed initial value 0.5
275      */
276     float targetUtilization_;
277 
278     IsObjectFinalizebleFunc isObjectFinalizebleFunc_ = nullptr;
279     RegisterFinalizeReferenceFunc registerFinalizeReferenceFunc_ = nullptr;
280     PandaVM *vm_ {nullptr};
281     MemStatsType *memStats_ {nullptr};
282     mem::GC *gc_ = nullptr;
283     RuntimeNotificationManager *notificationManager_ = nullptr;
284 };
285 
286 }  // namespace panda::mem
287 
288 #endif  // PANDA_MEM_HEAP_MANAGER_H
289