• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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