• 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 "runtime/include/class.h"
23 #include "runtime/include/mem/allocator.h"
24 #include "runtime/include/mem/panda_containers.h"
25 #include "runtime/include/object_header.h"
26 #include "runtime/include/thread.h"
27 #include "runtime/mem/frame_allocator-inl.h"
28 #include "runtime/mem/heap_verifier.h"
29 #include "runtime/mem/tlab.h"
30 #include "runtime/mem/gc/heap-space-misc/crossing_map_singleton.h"
31 
32 namespace panda {
33 // Forward declaration
34 class Runtime;
35 class PandaVM;
36 class RuntimeNotificationManager;
37 }  //  namespace panda
38 
39 namespace panda::mem {
40 
41 class HeapManager {
42 public:
43     bool Initialize(GCType gc_type, bool single_threaded, bool use_tlab, MemStatsType *mem_stats,
44                     InternalAllocatorPtr internal_allocator, bool create_pygote_space);
45 
46     bool Finalize();
47 
48     [[nodiscard]] ObjectHeader *AllocateObject(BaseClass *cls, size_t size, Alignment align = DEFAULT_ALIGNMENT,
49                                                ManagedThread *thread = nullptr);
50 
51     template <bool IsFirstClassClass = false>
52     [[nodiscard]] ObjectHeader *AllocateNonMovableObject(BaseClass *cls, size_t size,
53                                                          Alignment align = DEFAULT_ALIGNMENT,
54                                                          ManagedThread *thread = nullptr);
55 
56     /**
57      * \brief Allocates memory for ExtFrame, but do not construct it
58      * @param size - size of allocation (ExtFrame) in bytes
59      * @param ext_sz - size of frame extension in bytes
60      * @return pointer to Frame
61      */
62     [[nodiscard]] Frame *AllocateExtFrame(size_t size, size_t ext_sz);
63 
64     /**
65      * \brief Frees memory occupied by ExtFrame
66      * @param frame - pointer to Frame
67      * @param ext_sz - size of frame extension in bytes
68      */
69     void FreeExtFrame(Frame *frame, size_t ext_sz);
70 
71     CodeAllocator *GetCodeAllocator() const;
72 
73     InternalAllocatorPtr GetInternalAllocator();
74 
75     ObjectAllocatorPtr GetObjectAllocator();
76 
UseTLABForAllocations()77     bool UseTLABForAllocations()
78     {
79         return use_tlab_for_allocations_;
80     }
81 
82     bool CreateNewTLAB(ManagedThread *thread);
83 
GetTLABMaxAllocSize()84     size_t GetTLABMaxAllocSize()
85     {
86         return UseTLABForAllocations() ? objectAllocator_.AsObjectAllocator()->GetTLABMaxAllocSize() : 0;
87     }
88 
89     /**
90      * Register TLAB information in MemStats during changing TLAB in a thread
91      * or during thread destroying.
92      */
93     void RegisterTLAB(const TLAB *tlab);
94 
95     /**
96      * Prepare the heap before the fork process, The main function is to compact zygote space for fork subprocess
97      *
98      * @param
99      * @return void
100      */
101     void PreZygoteFork();
102 
103     /**
104      *  TODO :  Not yet implemented
105      *  To implement the getTargetHeapUtilization and nativeSetTargetHeapUtilization,
106      *  I set two functions and a fixed initial value here. They may need to be rewritten
107      */
108     float GetTargetHeapUtilization() const;
109 
110     void SetTargetHeapUtilization(float target);
111 
112     void DumpHeap(PandaOStringStream *o_string_stream);
113 
VerifyHeapReferences()114     size_t VerifyHeapReferences()
115     {
116         trace::ScopedTrace scoped_trace(__FUNCTION__);
117         size_t fail_count = 0;
118         HeapObjectVerifier verifier(this, &fail_count);
119         objectAllocator_->IterateOverObjects(verifier);
120         return verifier.GetFailCount();
121     }
122 
123     // Returns the maximum amount of memory a program can consume.
GetMaxMemory()124     size_t GetMaxMemory() const
125     {
126         return MemConfig::GetHeapSizeLimit();
127     }
128 
129     // Returns approximate amount of memory currently consumed by an application.
130     size_t GetTotalMemory() const;
131 
132     // Returns how much free memory we have until we need to grow the heap to perform an allocation.
133     size_t GetFreeMemory() const;
134 
135     // added for VMDebug::countInstancesOfClass and countInstancesOfClasses
136     void CountInstances(const PandaVector<Class *> &classes, bool assignable, uint64_t *counts);
137 
138     using IsObjectFinalizebleFunc = bool (*)(BaseClass *);
139     using RegisterFinalizeReferenceFunc = void (*)(ObjectHeader *, BaseClass *);
140     void SetIsFinalizableFunc(IsObjectFinalizebleFunc func);
141     void SetRegisterFinalizeReferenceFunc(RegisterFinalizeReferenceFunc func);
142 
143     bool IsObjectFinalized(BaseClass *cls);
144     void RegisterFinalizedObject(ObjectHeader *object, BaseClass *cls, bool is_object_finalizable);
145 
146     void SetPandaVM(PandaVM *vm);
147 
GetPandaVM()148     PandaVM *GetPandaVM() const
149     {
150         return vm_;
151     }
152 
GetGC()153     mem::GC *GetGC() const
154     {
155         return gc_;
156     }
157 
GetNotificationManager()158     RuntimeNotificationManager *GetNotificationManager() const
159     {
160         return notification_manager_;
161     }
162 
GetMemStats()163     MemStatsType *GetMemStats() const
164     {
165         return mem_stats_;
166     }
167 
HeapManager()168     HeapManager() : target_utilization_(DEFAULT_TARGET_UTILIZATION) {}
169 
170     ~HeapManager() = default;
171 
172     NO_COPY_SEMANTIC(HeapManager);
173     NO_MOVE_SEMANTIC(HeapManager);
174 
175 private:
176     template <GCType gc_type, MTModeT MTMode = MT_MODE_MULTI>
Initialize(MemStatsType * mem_stats,bool create_pygote_space)177     bool Initialize(MemStatsType *mem_stats, bool create_pygote_space)
178     {
179         ASSERT(!isInitialized_);
180         isInitialized_ = true;
181 
182         codeAllocator_ = new (std::nothrow) CodeAllocator(mem_stats);
183         // For now, crossing map is shared by diffrent VMs.
184         if (!CrossingMapSingleton::IsCreated()) {
185             CrossingMapSingleton::Create();
186         }
187         objectAllocator_ = new (std::nothrow)
188             typename AllocConfig<gc_type, MTMode>::ObjectAllocatorType(mem_stats, create_pygote_space);
189         return (codeAllocator_ != nullptr) && (internalAllocator_ != nullptr) && (objectAllocator_ != nullptr);
190     }
191 
192     /**
193      * Initialize GC bits and also zeroing memory for the whole Object memory
194      * @param cls - class
195      * @param mem - pointer to the ObjectHeader
196      * @return pointer to the ObjectHeader
197      */
198     ObjectHeader *InitObjectHeaderAtMem(BaseClass *cls, void *mem);
199 
200     /**
201      * Triggers GC if needed
202      */
203     void TriggerGCIfNeeded();
204 
205     void *TryGCAndAlloc(size_t size, Alignment align, ManagedThread *thread);
206 
207     void *AllocByTLAB(size_t size, ManagedThread *thread);
208 
209     void *AllocateMemoryForObject(size_t size, Alignment align, ManagedThread *thread);
210 
211     static constexpr float DEFAULT_TARGET_UTILIZATION = 0.5;
212 
213     bool isInitialized_ = false;
214     bool use_runtime_internal_allocator_ {true};
215     CodeAllocator *codeAllocator_ = nullptr;
216     InternalAllocatorPtr internalAllocator_ = nullptr;
217     ObjectAllocatorPtr objectAllocator_ = nullptr;
218 
219     bool use_tlab_for_allocations_ = false;
220 
221     /**
222      * StackFrameAllocator is per thread
223      */
224     StackFrameAllocator *GetCurrentStackFrameAllocator();
225 
226     friend class ::panda::Runtime;
227 
228     /**
229      * TODO : Target ideal heap utilization ratio.
230      * To implement the getTargetHeapUtilization and nativeSetTargetHeapUtilization, I set a variable here.
231      * It may need to be initialized, but now I give it a fixed initial value 0.5
232      */
233     float target_utilization_;
234 
235     IsObjectFinalizebleFunc IsObjectFinalizebleFunc_ = nullptr;
236     RegisterFinalizeReferenceFunc RegisterFinalizeReferenceFunc_ = nullptr;
237     PandaVM *vm_ {nullptr};
238     MemStatsType *mem_stats_ {nullptr};
239     mem::GC *gc_ = nullptr;
240     RuntimeNotificationManager *notification_manager_ = nullptr;
241 };
242 
243 }  // namespace panda::mem
244 
245 #endif  // PANDA_MEM_HEAP_MANAGER_H
246