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 #ifndef PANDA_RUNTIME_TOOLING_MEM_ALLOC_DUMPER_H 16 #define PANDA_RUNTIME_TOOLING_MEM_ALLOC_DUMPER_H 17 18 #include <functional> 19 #include <memory> 20 #include <string_view> 21 22 #include "pt_hooks_wrapper.h" 23 #include "include/mem/panda_smart_pointers.h" 24 #include "include/mem/panda_containers.h" 25 #include "include/runtime_notification.h" 26 #include "include/tooling/debug_interface.h" 27 #include "libpandabase/os/mutex.h" 28 #include "libpandabase/utils/span.h" 29 #include "runtime/include/mem/panda_containers.h" 30 #include "runtime/include/method.h" 31 #include "runtime/include/runtime.h" 32 #include "runtime/include/panda_vm.h" 33 #include "runtime/include/tooling/debug_interface.h" 34 #include "runtime/thread_manager.h" 35 36 namespace ark::tooling { 37 class MemoryAllocationDumper : public RuntimeListener { 38 public: MemoryAllocationDumper(const PandaString & dumpFile,const Runtime * runtime)39 explicit MemoryAllocationDumper(const PandaString &dumpFile, const Runtime *runtime) : runtime_(runtime) 40 { 41 dumpstream_.open(dumpFile.c_str(), std::ios::out); 42 runtime_->GetNotificationManager()->AddListener(this, DUMP_EVENT_MASK); 43 } 44 ~MemoryAllocationDumper()45 ~MemoryAllocationDumper() override 46 { 47 runtime_->GetNotificationManager()->RemoveListener(this, DUMP_EVENT_MASK); 48 dumpstream_.close(); 49 } 50 51 // RuntimeListener methods ObjectAlloc(BaseClass * klass,ObjectHeader * object,ManagedThread * thread,size_t size)52 void ObjectAlloc(BaseClass *klass, ObjectHeader *object, ManagedThread *thread, size_t size) override 53 { 54 if (thread == nullptr) { 55 thread = ManagedThread::GetCurrent(); 56 if (thread == nullptr) { 57 DumpNotAllocEvent("NULLPTR_THREAD", "ObjectAlloc"); 58 } 59 } 60 ASSERT(thread == ManagedThread::GetCurrent()); 61 62 PandaString klassName; 63 if (klass->IsDynamicClass()) { 64 klassName = "Dynamic"; 65 } else { 66 klassName = ClassHelper::GetName<PandaString>(static_cast<Class *>(klass)->GetDescriptor()); 67 } 68 69 DumpAllocation("NO_ERROR", "ObjectAlloc", klassName, object, size); 70 } 71 GarbageCollectorStart()72 void GarbageCollectorStart() override 73 { 74 DumpNotAllocEvent("NO_ERROR", "GarbageCollectorStart"); 75 } 76 GarbageCollectorFinish()77 void GarbageCollectorFinish() override 78 { 79 DumpNotAllocEvent("NO_ERROR", "GarbageCollectorFinish"); 80 } 81 82 private: 83 // Add one func to use lock in right way DumpAllocation(const char * err,const char * caller,const PandaString & klassName,ObjectHeader * object,size_t size)84 void DumpAllocation(const char *err, const char *caller, const PandaString &klassName, ObjectHeader *object, 85 size_t size) 86 { 87 os::memory::LockHolder lock(lock_); 88 const void *rawptr = static_cast<const void *>(object); 89 dumpstream_ << err << "," << time::GetCurrentTimeInMicros() << "," << caller << "," << klassName << "," 90 << rawptr << "," << size << std::endl; 91 } 92 DumpNotAllocEvent(const char * err,const char * caller)93 void DumpNotAllocEvent(const char *err, const char *caller) 94 { 95 os::memory::LockHolder lock(lock_); 96 dumpstream_ << err << "," << time::GetCurrentTimeInMicros() << "," << caller << std::endl; 97 } 98 99 static constexpr uint32_t DUMP_EVENT_MASK = RuntimeNotificationManager::Event::GARBAGE_COLLECTOR_EVENTS | 100 RuntimeNotificationManager::Event::ALLOCATION_EVENTS; 101 102 const Runtime *runtime_; 103 std::ofstream dumpstream_; 104 os::memory::Mutex lock_; 105 106 NO_COPY_SEMANTIC(MemoryAllocationDumper); 107 NO_MOVE_SEMANTIC(MemoryAllocationDumper); 108 }; 109 } // namespace ark::tooling 110 111 #endif // PANDA_RUNTIME_TOOLING_MEM_ALLOC_DUMPER_H 112