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 37namespace panda::ecmascript::tooling { 38class HeapProfilerImpl final { 39public: 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: 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 enum class Method { 83 ADD_INSPECTED_HEAP_OBJECT, 84 COLLECT_GARBAGE, 85 ENABLE, 86 DISABLE, 87 GET_HEAP_OBJECT_ID, 88 GET_OBJECT_BY_HEAP_OBJECT_ID, 89 GET_SAMPLING_PROFILE, 90 START_SAMPLING, 91 START_TRACKING_HEAP_OBJECTS, 92 STOP_SAMPLING, 93 STOP_TRACKING_HEAP_OBJECTS, 94 TAKE_HEAP_SNAPSHOT, 95 UNKNOWN 96 }; 97 Method GetMethodEnum(const std::string& method); 98 99 private: 100 NO_COPY_SEMANTIC(DispatcherImpl); 101 NO_MOVE_SEMANTIC(DispatcherImpl); 102 103 std::unique_ptr<HeapProfilerImpl> heapprofiler_ {}; 104 }; 105 106private: 107 NO_COPY_SEMANTIC(HeapProfilerImpl); 108 NO_MOVE_SEMANTIC(HeapProfilerImpl); 109 110 class Frontend { 111 public: 112 explicit Frontend(ProtocolChannel *channel) : channel_(channel) {} 113 ~Frontend() = default; 114 115 void AddHeapSnapshotChunk(char *data, int32_t size); 116 void ReportHeapSnapshotProgress(int32_t done, int32_t total); 117 void HeapStatsUpdate(HeapStat* updateData, int32_t count); 118 void LastSeenObjectId(int32_t lastSeenObjectId, int64_t timeStampUs); 119 void ResetProfiles(); 120 121 private: 122 bool AllowNotify() const; 123 124 ProtocolChannel *channel_ {nullptr}; 125 }; 126 127 class HeapProfilerStream final : public Stream { 128 public: 129 explicit HeapProfilerStream(Frontend *frontend) 130 : frontend_(frontend) {} 131 132 void EndOfStream() override {} 133 int GetSize() override 134 { 135 static const int heapProfilerChunkSise = static_cast<int>(100_KB); 136 return heapProfilerChunkSise; 137 } 138 bool WriteChunk(char *data, int32_t size) override 139 { 140 if (!Good()) { 141 return false; 142 } 143 frontend_->AddHeapSnapshotChunk(data, size); 144 return true; 145 } 146 bool WriteBinBlock(char *data, int32_t size) override 147 { 148 return WriteChunk(data, size); 149 } 150 bool Good() override 151 { 152 return frontend_ != nullptr; 153 } 154 155 void UpdateHeapStats(HeapStat* updateData, int32_t count) override 156 { 157 if (!Good()) { 158 return; 159 } 160 frontend_->HeapStatsUpdate(updateData, count); 161 } 162 163 void UpdateLastSeenObjectId(int32_t lastSeenObjectId, int64_t timeStampUs) override 164 { 165 if (!Good()) { 166 return; 167 } 168 frontend_->LastSeenObjectId(lastSeenObjectId, timeStampUs); 169 } 170 171 private: 172 NO_COPY_SEMANTIC(HeapProfilerStream); 173 NO_MOVE_SEMANTIC(HeapProfilerStream); 174 175 Frontend *frontend_ {nullptr}; 176 }; 177 178 class HeapProfilerProgress final : public Progress { 179 public: 180 explicit HeapProfilerProgress(Frontend *frontend) 181 : frontend_(frontend) {} 182 183 void ReportProgress(int32_t done, int32_t total) override 184 { 185 frontend_->ReportHeapSnapshotProgress(done, total); 186 } 187 188 private: 189 NO_COPY_SEMANTIC(HeapProfilerProgress); 190 NO_MOVE_SEMANTIC(HeapProfilerProgress); 191 192 Frontend *frontend_ {nullptr}; 193 }; 194 195 void InitializeExtendedProtocolsList(); 196 197 const EcmaVM *vm_ {nullptr}; 198 Frontend frontend_; 199 HeapProfilerStream stream_; 200 std::vector<std::string> heapProfilerExtendedProtocols_ {}; 201#if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER) 202 uv_timer_t handle_ {}; 203#endif 204 205 friend class HeapProfilerImplFriendTest; 206}; 207} // namespace panda::ecmascript::tooling 208#endif 209