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