• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef PANDA_RUNTIME_MEM_HEAP_MANAGER_H_
17 #define PANDA_RUNTIME_MEM_HEAP_MANAGER_H_
18 
19 #include <cstddef>
20 #include <memory>
21 
22 #include "libpandabase/utils/logger.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/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 class HeapManager {
43 public:
44     bool Initialize(GCType gc_type, bool single_threaded, bool use_tlab, MemStatsType *mem_stats,
45                     InternalAllocatorPtr internal_allocator, bool create_pygote_space);
46 
47     bool Finalize();
48 
49     [[nodiscard]] ObjectHeader *AllocateObject(BaseClass *cls, size_t size, Alignment align = DEFAULT_ALIGNMENT,
50                                                MTManagedThread *thread = nullptr);
51 
52     template <bool IsFirstClassClass = false>
53     [[nodiscard]] ObjectHeader *AllocateNonMovableObject(BaseClass *cls, size_t size,
54                                                          Alignment align = DEFAULT_ALIGNMENT,
55                                                          ManagedThread *thread = nullptr);
56 
57     /**
58      * \brief Allocates memory for Frame, but do not construct it
59      * @param size - size in bytes
60      * @return pointer to allocated memory
61      */
62     [[nodiscard]] Frame *AllocateFrame(size_t size);
63 
64     /**
65      * \brief Frees memory occupied by Frame
66      * @param frame_ptr - pointer to Frame
67      */
68     void FreeFrame(Frame *frame_ptr);
69 
70     CodeAllocator *GetCodeAllocator() const;
71 
72     InternalAllocatorPtr GetInternalAllocator();
73 
74     ObjectAllocatorPtr GetObjectAllocator();
75 
UseTLABForAllocations()76     bool UseTLABForAllocations() const
77     {
78         return use_tlab_for_allocations_;
79     }
80 
81     bool CreateNewTLAB(ManagedThread *thread);
82 
GetTLABMaxAllocSize()83     size_t GetTLABMaxAllocSize()
84     {
85         return objectAllocator_.AsObjectAllocator()->GetTLABMaxAllocSize();
86     }
87 
88     /**
89      * Register TLAB information in MemStats during changing TLAB in a thread
90      * or during thread destroying.
91      */
92     void RegisterTLAB(TLAB *tlab);
93 
94     /**
95      * Prepare the heap before the fork process, The main function is to compact zygote space for fork subprocess
96      *
97      * @param
98      * @return void
99      */
100     void PreZygoteFork();
101 
102     /**
103      *  To implement the getTargetHeapUtilization and nativeSetTargetHeapUtilization,
104      *  I set two functions and a fixed initial value here. They may need to be rewritten
105      */
106     float GetTargetHeapUtilization() const;
107 
108     void SetTargetHeapUtilization(float target);
109 
110     void DumpHeap(PandaOStringStream *o_string_stream);
111 
VerifyHeapReferences()112     size_t VerifyHeapReferences()
113     {
114         trace::ScopedTrace scoped_trace(__FUNCTION__);
115         size_t fail_count = 0;
116         HeapObjectVerifier verifier(this, &fail_count);
117         objectAllocator_->IterateOverObjects(verifier);
118         return verifier.GetFailCount();
119     }
120 
121     // Implements java.lang.Runtime.maxMemory.
122     // Returns the maximum amount of memory a program can consume.
GetMaxMemory()123     size_t GetMaxMemory() const
124     {
125         return MemConfig::GetObjectPoolSize();
126     }
127 
128     // Implements java.lang.Runtime.totalMemory.
129     // Returns approximate amount of memory currently consumed by an application.
130     size_t GetTotalMemory() const;
131 
132     // Implements java.lang.Runtime.freeMemory.
133     // Returns how much free memory we have until we need to grow the heap to perform an allocation.
134     size_t GetFreeMemory() const;
135 
136     // added for VMDebug::countInstancesOfClass and countInstancesOfClasses
137     void CountInstances(const PandaVector<Class *> &classes, bool assignable, uint64_t *counts);
138 
139     using IsObjectFinalizebleFunc = bool (*)(BaseClass *);
140     using RegisterFinalizeReferenceFunc = void (*)(ObjectHeader *, BaseClass *);
141     void SetIsFinalizableFunc(IsObjectFinalizebleFunc func);
142     void SetRegisterFinalizeReferenceFunc(RegisterFinalizeReferenceFunc func);
143 
144     bool IsObjectFinalized(BaseClass *cls);
145     void RegisterFinalizedObject(ObjectHeader *object, BaseClass *cls, bool is_object_finalizable);
146 
147     void SetPandaVM(PandaVM *vm);
148 
GetPandaVM()149     PandaVM *GetPandaVM() const
150     {
151         return vm_;
152     }
153 
GetGC()154     mem::GC *GetGC() const
155     {
156         return gc_;
157     }
158 
GetNotificationManager()159     RuntimeNotificationManager *GetNotificationManager() const
160     {
161         return notification_manager_;
162     }
163 
GetMemStats()164     MemStatsType *GetMemStats() const
165     {
166         return mem_stats_;
167     }
168 
HeapManager()169     HeapManager() : target_utilization_(DEFAULT_TARGET_UTILIZATION) {}
170 
171     ~HeapManager() = default;
172 
173     NO_COPY_SEMANTIC(HeapManager);
174     NO_MOVE_SEMANTIC(HeapManager);
175 
176 private:
177     template <GCType gc_type, MTModeT MTMode = MT_MODE_MULTI>
Initialize(MemStatsType * mem_stats,bool create_pygote_space)178     bool Initialize(MemStatsType *mem_stats, bool create_pygote_space)
179     {
180         ASSERT(!isInitialized_);
181         isInitialized_ = true;
182 
183         codeAllocator_ = new (std::nothrow) CodeAllocator(mem_stats);
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, panda::MTManagedThread *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      * To implement the getTargetHeapUtilization and nativeSetTargetHeapUtilization, I set a variable here.
230      * It may need to be initialized, but now I give it a fixed initial value 0.5
231      */
232     float target_utilization_;
233 
234     IsObjectFinalizebleFunc IsObjectFinalizebleFunc_ = nullptr;
235     RegisterFinalizeReferenceFunc RegisterFinalizeReferenceFunc_ = nullptr;
236     PandaVM *vm_ {nullptr};
237     MemStatsType *mem_stats_ {nullptr};
238     mem::GC *gc_ = nullptr;
239     RuntimeNotificationManager *notification_manager_ = nullptr;
240 };
241 
242 }  // namespace panda::mem
243 
244 #endif  // PANDA_RUNTIME_MEM_HEAP_MANAGER_H_
245