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