• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 ECMASCRIPT_DFX_HPROF_HEAP_PROFILER_H
17 #define ECMASCRIPT_DFX_HPROF_HEAP_PROFILER_H
18 
19 #include "ecmascript/dfx/hprof/heap_profiler_interface.h"
20 #include "ecmascript/dfx/hprof/heap_snapshot_json_serializer.h"
21 #include "ecmascript/dfx/hprof/heap_tracker.h"
22 #include "ecmascript/ecma_macros.h"
23 #include "ecmascript/mem/c_containers.h"
24 #include "ecmascript/dfx/hprof/file_stream.h"
25 #include "ecmascript/dfx/hprof/heap_sampling.h"
26 #include "ecmascript/dfx/hprof/progress.h"
27 
28 namespace panda::ecmascript {
29 class HeapSnapshot;
30 class EcmaVM;
31 
32 class EntryIdMap {
33 public:
34     EntryIdMap() = default;
35     ~EntryIdMap() = default;
36     NO_COPY_SEMANTIC(EntryIdMap);
37     NO_MOVE_SEMANTIC(EntryIdMap);
38 
39     static constexpr uint32_t SEQ_STEP = 2;
40     std::pair<bool, uint32_t> FindId(Address addr);
41     bool InsertId(Address addr, uint32_t id);
42     bool EraseId(Address addr);
43     bool Move(Address oldAddr, Address forwardAddr);
44     void RemoveDeadEntryId(HeapSnapshot *snapshot);
GetNextId()45     uint32_t GetNextId()
46     {
47         nextId_ += SEQ_STEP;
48         return nextId_ - SEQ_STEP;
49     }
GetLastId()50     uint32_t GetLastId()
51     {
52         return nextId_ - SEQ_STEP;
53     }
GetIdCount()54     size_t GetIdCount()
55     {
56         return idMap_.size();
57     }
58 
59 private:
60     uint32_t nextId_ {3U};  // 1 Reversed for SyntheticRoot
61     CUnorderedMap<Address, uint32_t> idMap_ {};
62 };
63 
64 class HeapProfiler : public HeapProfilerInterface {
65 public:
66     NO_MOVE_SEMANTIC(HeapProfiler);
67     NO_COPY_SEMANTIC(HeapProfiler);
68     explicit HeapProfiler(const EcmaVM *vm);
69     ~HeapProfiler() override;
70 
71     enum class SampleType { ONE_SHOT, REAL_TIME };
72 
73     void AllocationEvent(TaggedObject *address, size_t size) override;
74     void MoveEvent(uintptr_t address, TaggedObject *forwardAddress, size_t size) override;
75     /**
76      * dump the specific snapshot in target format
77      */
78     bool DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress = nullptr,
79                           bool isVmMode = true, bool isPrivate = false, bool captureNumericValue = false) override;
80 
81     void AddSnapshot(HeapSnapshot *snapshot);
82 
83     bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
84                            bool traceAllocation = false, bool newThread = true) override;
85     bool StopHeapTracking(Stream *stream, Progress *progress = nullptr, bool newThread = true) override;
86     bool UpdateHeapTracking(Stream *stream) override;
87     bool StartHeapSampling(uint64_t samplingInterval, int stackDepth = 128) override;
88     void StopHeapSampling() override;
89     const struct SamplingInfo *GetAllocationProfile() override;
GetIdCount()90     size_t GetIdCount() override
91     {
92         return entryIdMap_->GetIdCount();
93     }
GetEntryIdMap()94     EntryIdMap *GetEntryIdMap() const
95     {
96         return const_cast<EntryIdMap *>(entryIdMap_);
97     }
GetChunk()98     Chunk *GetChunk() const
99     {
100         return const_cast<Chunk *>(&chunk_);
101     }
102 private:
103     /**
104      * trigger full gc to make sure no unreachable objects in heap
105      */
106     bool ForceFullGC(const EcmaVM *vm);
107 
108     /**
109      * make a new heap snapshot and put it into a container eg, vector
110      */
111     HeapSnapshot *MakeHeapSnapshot(SampleType sampleType, bool isVmMode = true,
112                                    bool isPrivate = false, bool captureNumericValue = false,
113                                    bool traceAllocation = false);
114     std::string GenDumpFileName(DumpFormat dumpFormat);
115     CString GetTimeStamp();
116     void UpdateHeapObjects(HeapSnapshot *snapshot);
117     void ClearSnapshot();
118 
119     const size_t MAX_NUM_HPROF = 5;  // ~10MB
120     const EcmaVM *vm_;
121     CVector<HeapSnapshot *> hprofs_;
122     HeapSnapshotJSONSerializer *jsonSerializer_ {nullptr};
123     bool isProfiling_ {false};
124     EntryIdMap* entryIdMap_;
125     std::unique_ptr<HeapTracker> heapTracker_;
126     Chunk chunk_;
127     std::unique_ptr<HeapSampling> heapSampling_ {nullptr};
128     os::memory::Mutex mutex_;
129 };
130 }  // namespace panda::ecmascript
131 #endif  // ECMASCRIPT_DFX_HPROF_HEAP_PROFILER_H
132