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 ECMASCRIPT_TOOLING_AGENT_HEAPPROFILER_IMPL_H 17 #define ECMASCRIPT_TOOLING_AGENT_HEAPPROFILER_IMPL_H 18 19 #include <uv.h> 20 21 #include "base/pt_params.h" 22 #include "base/pt_events.h" 23 #include "base/pt_returns.h" 24 #include "dispatcher.h" 25 #include "protocol_handler.h" 26 #include "protocol_channel.h" 27 28 #include "ecmascript/dfx/hprof/progress.h" 29 #include "ecmascript/dfx/hprof/stream.h" 30 #include "ecmascript/napi/include/dfx_jsnapi.h" 31 #include "libpandabase/macros.h" 32 33 #include <sys/time.h> 34 35 namespace panda::ecmascript::tooling { 36 class HeapProfilerImpl final { 37 public: HeapProfilerImpl(const EcmaVM * vm,ProtocolChannel * channel)38 explicit HeapProfilerImpl(const EcmaVM *vm, ProtocolChannel *channel) 39 : vm_(vm), frontend_(channel), stream_(&frontend_) {} 40 ~HeapProfilerImpl() = default; 41 42 DispatchResponse AddInspectedHeapObject(const AddInspectedHeapObjectParams ¶ms); 43 DispatchResponse CollectGarbage(); 44 DispatchResponse Enable(); 45 DispatchResponse Disable(); 46 DispatchResponse GetHeapObjectId(const GetHeapObjectIdParams ¶ms, HeapSnapshotObjectId *objectId); 47 DispatchResponse GetObjectByHeapObjectId(const GetObjectByHeapObjectIdParams ¶ms, 48 std::unique_ptr<RemoteObject> *remoteObjectResult); 49 DispatchResponse GetSamplingProfile(std::unique_ptr<SamplingHeapProfile> *profile); 50 DispatchResponse StartSampling(const StartSamplingParams ¶ms); 51 DispatchResponse StartTrackingHeapObjects(const StartTrackingHeapObjectsParams ¶ms); 52 static void HeapTrackingCallback(uv_timer_t* handle); 53 DispatchResponse StopSampling(std::unique_ptr<SamplingHeapProfile> *profile); 54 DispatchResponse StopTrackingHeapObjects(const StopTrackingHeapObjectsParams ¶ms); 55 // The params type of TakeHeapSnapshot is the same as of StopTrackingHeapObjects. 56 DispatchResponse TakeHeapSnapshot(const StopTrackingHeapObjectsParams ¶ms); 57 58 class DispatcherImpl final : public DispatcherBase { 59 public: DispatcherImpl(ProtocolChannel * channel,std::unique_ptr<HeapProfilerImpl> heapprofiler)60 DispatcherImpl(ProtocolChannel *channel, std::unique_ptr<HeapProfilerImpl> heapprofiler) 61 : DispatcherBase(channel), heapprofiler_(std::move(heapprofiler)) {} 62 ~DispatcherImpl() override = default; 63 64 void Dispatch(const DispatchRequest &request) override; 65 void AddInspectedHeapObject(const DispatchRequest &request); 66 void CollectGarbage(const DispatchRequest &request); 67 void Enable(const DispatchRequest &request); 68 void Disable(const DispatchRequest &request); 69 void GetHeapObjectId(const DispatchRequest &request); 70 void GetObjectByHeapObjectId(const DispatchRequest &request); 71 void GetSamplingProfile(const DispatchRequest &request); 72 void StartSampling(const DispatchRequest &request); 73 void StartTrackingHeapObjects(const DispatchRequest &request); 74 void StopSampling(const DispatchRequest &request); 75 void StopTrackingHeapObjects(const DispatchRequest &request); 76 void TakeHeapSnapshot(const DispatchRequest &request); 77 78 private: 79 NO_COPY_SEMANTIC(DispatcherImpl); 80 NO_MOVE_SEMANTIC(DispatcherImpl); 81 82 using AgentHandler = void (HeapProfilerImpl::DispatcherImpl::*)(const DispatchRequest &request); 83 std::unique_ptr<HeapProfilerImpl> heapprofiler_ {}; 84 }; 85 86 private: 87 NO_COPY_SEMANTIC(HeapProfilerImpl); 88 NO_MOVE_SEMANTIC(HeapProfilerImpl); 89 90 class Frontend { 91 public: Frontend(ProtocolChannel * channel)92 explicit Frontend(ProtocolChannel *channel) : channel_(channel) {} 93 ~Frontend() = default; 94 95 void AddHeapSnapshotChunk(char *data, int32_t size); 96 void ReportHeapSnapshotProgress(int32_t done, int32_t total); 97 void HeapStatsUpdate(HeapStat* updateData, int32_t count); 98 void LastSeenObjectId(int32_t lastSeenObjectId, int64_t timeStampUs); 99 void ResetProfiles(); 100 101 private: 102 bool AllowNotify() const; 103 104 ProtocolChannel *channel_ {nullptr}; 105 }; 106 107 class HeapProfilerStream final : public Stream { 108 public: HeapProfilerStream(Frontend * frontend)109 explicit HeapProfilerStream(Frontend *frontend) 110 : frontend_(frontend) {} 111 EndOfStream()112 void EndOfStream() override {} GetSize()113 int GetSize() override 114 { 115 static const int heapProfilerChunkSise = 100_KB; 116 return heapProfilerChunkSise; 117 } WriteChunk(char * data,int32_t size)118 bool WriteChunk(char *data, int32_t size) override 119 { 120 if (!Good()) { 121 return false; 122 } 123 frontend_->AddHeapSnapshotChunk(data, size); 124 return true; 125 } Good()126 bool Good() override 127 { 128 return frontend_ != nullptr; 129 } 130 UpdateHeapStats(HeapStat * updateData,int32_t count)131 void UpdateHeapStats(HeapStat* updateData, int32_t count) override 132 { 133 if (!Good()) { 134 return; 135 } 136 frontend_->HeapStatsUpdate(updateData, count); 137 } 138 UpdateLastSeenObjectId(int32_t lastSeenObjectId,int64_t timeStampUs)139 void UpdateLastSeenObjectId(int32_t lastSeenObjectId, int64_t timeStampUs) override 140 { 141 if (!Good()) { 142 return; 143 } 144 frontend_->LastSeenObjectId(lastSeenObjectId, timeStampUs); 145 } 146 147 private: 148 NO_COPY_SEMANTIC(HeapProfilerStream); 149 NO_MOVE_SEMANTIC(HeapProfilerStream); 150 151 Frontend *frontend_ {nullptr}; 152 }; 153 154 class HeapProfilerProgress final : public Progress { 155 public: HeapProfilerProgress(Frontend * frontend)156 explicit HeapProfilerProgress(Frontend *frontend) 157 : frontend_(frontend) {} 158 ReportProgress(int32_t done,int32_t total)159 void ReportProgress(int32_t done, int32_t total) override 160 { 161 frontend_->ReportHeapSnapshotProgress(done, total); 162 } 163 164 private: 165 NO_COPY_SEMANTIC(HeapProfilerProgress); 166 NO_MOVE_SEMANTIC(HeapProfilerProgress); 167 168 Frontend *frontend_ {nullptr}; 169 }; 170 171 const EcmaVM *vm_ {nullptr}; 172 Frontend frontend_; 173 HeapProfilerStream stream_; 174 uv_timer_t handle_ {}; 175 }; 176 } // namespace panda::ecmascript::tooling 177 #endif