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