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 #include "ecmascript/tooling/agent/heapprofiler_impl.h" 17 18 namespace panda::ecmascript::tooling { Dispatch(const DispatchRequest & request)19 void HeapProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) 20 { 21 static std::unordered_map<std::string, AgentHandler> dispatcherTable { 22 { "addInspectedHeapObject", &HeapProfilerImpl::DispatcherImpl::AddInspectedHeapObject }, 23 { "collectGarbage", &HeapProfilerImpl::DispatcherImpl::CollectGarbage }, 24 { "enable", &HeapProfilerImpl::DispatcherImpl::Enable }, 25 { "disable", &HeapProfilerImpl::DispatcherImpl::Disable }, 26 { "getHeapObjectId", &HeapProfilerImpl::DispatcherImpl::GetHeapObjectId }, 27 { "getObjectByHeapObjectId", &HeapProfilerImpl::DispatcherImpl::GetObjectByHeapObjectId }, 28 { "getSamplingProfile", &HeapProfilerImpl::DispatcherImpl::GetSamplingProfile }, 29 { "startSampling", &HeapProfilerImpl::DispatcherImpl::StartSampling }, 30 { "startTrackingHeapObjects", &HeapProfilerImpl::DispatcherImpl::StartTrackingHeapObjects }, 31 { "stopSampling", &HeapProfilerImpl::DispatcherImpl::StopSampling }, 32 { "stopTrackingHeapObjects", &HeapProfilerImpl::DispatcherImpl::StopTrackingHeapObjects }, 33 { "takeHeapSnapshot", &HeapProfilerImpl::DispatcherImpl::TakeHeapSnapshot } 34 }; 35 36 const std::string &method = request.GetMethod(); 37 LOG(DEBUG, DEBUGGER) << "dispatch [" << method << "] to HeapProfilerImpl"; 38 auto entry = dispatcherTable.find(method); 39 if (entry != dispatcherTable.end() && entry->second != nullptr) { 40 (this->*(entry->second))(request); 41 } else { 42 SendResponse(request, DispatchResponse::Fail("Unknown method: " + method)); 43 } 44 } 45 AddInspectedHeapObject(const DispatchRequest & request)46 void HeapProfilerImpl::DispatcherImpl::AddInspectedHeapObject(const DispatchRequest &request) 47 { 48 std::unique_ptr<AddInspectedHeapObjectParams> params = AddInspectedHeapObjectParams::Create(request.GetParams()); 49 if (params == nullptr) { 50 SendResponse(request, DispatchResponse::Fail("wrong params")); 51 return; 52 } 53 DispatchResponse response = heapprofiler_->AddInspectedHeapObject(*params); 54 SendResponse(request, response); 55 } 56 CollectGarbage(const DispatchRequest & request)57 void HeapProfilerImpl::DispatcherImpl::CollectGarbage(const DispatchRequest &request) 58 { 59 DispatchResponse response = heapprofiler_->CollectGarbage(); 60 SendResponse(request, response); 61 } 62 Enable(const DispatchRequest & request)63 void HeapProfilerImpl::DispatcherImpl::Enable(const DispatchRequest &request) 64 { 65 DispatchResponse response = heapprofiler_->Enable(); 66 SendResponse(request, response); 67 } 68 Disable(const DispatchRequest & request)69 void HeapProfilerImpl::DispatcherImpl::Disable(const DispatchRequest &request) 70 { 71 DispatchResponse response = heapprofiler_->Disable(); 72 SendResponse(request, response); 73 } 74 GetHeapObjectId(const DispatchRequest & request)75 void HeapProfilerImpl::DispatcherImpl::GetHeapObjectId(const DispatchRequest &request) 76 { 77 std::unique_ptr<GetHeapObjectIdParams> params = GetHeapObjectIdParams::Create(request.GetParams()); 78 if (params == nullptr) { 79 SendResponse(request, DispatchResponse::Fail("wrong params")); 80 return; 81 } 82 83 HeapSnapshotObjectId objectId; 84 DispatchResponse response = heapprofiler_->GetHeapObjectId(*params, &objectId); 85 GetHeapObjectIdReturns result(std::move(objectId)); 86 SendResponse(request, response, result); 87 } 88 GetObjectByHeapObjectId(const DispatchRequest & request)89 void HeapProfilerImpl::DispatcherImpl::GetObjectByHeapObjectId(const DispatchRequest &request) 90 { 91 std::unique_ptr<GetObjectByHeapObjectIdParams> params = GetObjectByHeapObjectIdParams::Create(request.GetParams()); 92 if (params == nullptr) { 93 SendResponse(request, DispatchResponse::Fail("wrong params")); 94 return; 95 } 96 97 std::unique_ptr<RemoteObject> remoteObjectResult; 98 DispatchResponse response = heapprofiler_->GetObjectByHeapObjectId(*params, &remoteObjectResult); 99 GetObjectByHeapObjectIdReturns result(std::move(remoteObjectResult)); 100 SendResponse(request, response, result); 101 } 102 GetSamplingProfile(const DispatchRequest & request)103 void HeapProfilerImpl::DispatcherImpl::GetSamplingProfile(const DispatchRequest &request) 104 { 105 std::unique_ptr<SamplingHeapProfile> profile; 106 DispatchResponse response = heapprofiler_->GetSamplingProfile(&profile); 107 // The return value type of GetSamplingProfile is the same as of StopSampling. 108 StopSamplingReturns result(std::move(profile)); 109 SendResponse(request, response, result); 110 } 111 StartSampling(const DispatchRequest & request)112 void HeapProfilerImpl::DispatcherImpl::StartSampling(const DispatchRequest &request) 113 { 114 std::unique_ptr<StartSamplingParams> params = StartSamplingParams::Create(request.GetParams()); 115 if (params == nullptr) { 116 SendResponse(request, DispatchResponse::Fail("wrong params")); 117 return; 118 } 119 DispatchResponse response = heapprofiler_->StartSampling(*params); 120 SendResponse(request, response); 121 } 122 StartTrackingHeapObjects(const DispatchRequest & request)123 void HeapProfilerImpl::DispatcherImpl::StartTrackingHeapObjects(const DispatchRequest &request) 124 { 125 std::unique_ptr<StartTrackingHeapObjectsParams> params = 126 StartTrackingHeapObjectsParams::Create(request.GetParams()); 127 if (params == nullptr) { 128 SendResponse(request, DispatchResponse::Fail("wrong params")); 129 return; 130 } 131 DispatchResponse response = heapprofiler_->StartTrackingHeapObjects(*params); 132 SendResponse(request, response); 133 } 134 135 StopSampling(const DispatchRequest & request)136 void HeapProfilerImpl::DispatcherImpl::StopSampling(const DispatchRequest &request) 137 { 138 std::unique_ptr<SamplingHeapProfile> profile; 139 DispatchResponse response = heapprofiler_->StopSampling(&profile); 140 StopSamplingReturns result(std::move(profile)); 141 SendResponse(request, response, result); 142 } 143 StopTrackingHeapObjects(const DispatchRequest & request)144 void HeapProfilerImpl::DispatcherImpl::StopTrackingHeapObjects(const DispatchRequest &request) 145 { 146 std::unique_ptr<StopTrackingHeapObjectsParams> params = StopTrackingHeapObjectsParams::Create(request.GetParams()); 147 if (params == nullptr) { 148 SendResponse(request, DispatchResponse::Fail("wrong params")); 149 return; 150 } 151 DispatchResponse response = heapprofiler_->StopTrackingHeapObjects(*params); 152 SendResponse(request, response); 153 } 154 TakeHeapSnapshot(const DispatchRequest & request)155 void HeapProfilerImpl::DispatcherImpl::TakeHeapSnapshot(const DispatchRequest &request) 156 { 157 std::unique_ptr<StopTrackingHeapObjectsParams> params = StopTrackingHeapObjectsParams::Create(request.GetParams()); 158 if (params == nullptr) { 159 SendResponse(request, DispatchResponse::Fail("wrong params")); 160 return; 161 } 162 DispatchResponse response = heapprofiler_->TakeHeapSnapshot(*params); 163 SendResponse(request, response); 164 } 165 AllowNotify() const166 bool HeapProfilerImpl::Frontend::AllowNotify() const 167 { 168 return channel_ != nullptr; 169 } 170 AddHeapSnapshotChunk(char * data,int32_t size)171 void HeapProfilerImpl::Frontend::AddHeapSnapshotChunk(char *data, int32_t size) 172 { 173 if (!AllowNotify()) { 174 return; 175 } 176 177 tooling::AddHeapSnapshotChunk addHeapSnapshotChunk; 178 addHeapSnapshotChunk.GetChunk().resize(size); 179 for (int32_t i = 0; i < size; ++i) { 180 addHeapSnapshotChunk.GetChunk()[i] = data[i]; 181 } 182 183 channel_->SendNotification(addHeapSnapshotChunk); 184 } 185 ReportHeapSnapshotProgress(int32_t done,int32_t total)186 void HeapProfilerImpl::Frontend::ReportHeapSnapshotProgress(int32_t done, int32_t total) 187 { 188 if (!AllowNotify()) { 189 return; 190 } 191 192 tooling::ReportHeapSnapshotProgress reportHeapSnapshotProgress; 193 reportHeapSnapshotProgress.SetDone(done).SetTotal(total); 194 if (done >= total) { 195 reportHeapSnapshotProgress.SetFinished(true); 196 } 197 channel_->SendNotification(reportHeapSnapshotProgress); 198 } 199 HeapStatsUpdate(HeapStat * updateData,int32_t count)200 void HeapProfilerImpl::Frontend::HeapStatsUpdate(HeapStat* updateData, int32_t count) 201 { 202 if (!AllowNotify()) { 203 return; 204 } 205 std::vector<int32_t> statsDiff; 206 for (int32_t i = 0; i < count; ++i) { 207 statsDiff.emplace_back(updateData[i].index_); 208 statsDiff.emplace_back(updateData[i].count_); 209 statsDiff.emplace_back(updateData[i].size_); 210 } 211 tooling::HeapStatsUpdate heapStatsUpdate; 212 heapStatsUpdate.SetStatsUpdate(std::move(statsDiff)); 213 channel_->SendNotification(heapStatsUpdate); 214 } 215 LastSeenObjectId(int32_t lastSeenObjectId)216 void HeapProfilerImpl::Frontend::LastSeenObjectId(int32_t lastSeenObjectId) 217 { 218 if (!AllowNotify()) { 219 return; 220 } 221 222 tooling::LastSeenObjectId lastSeenObjectIdEvent; 223 lastSeenObjectIdEvent.SetLastSeenObjectId(lastSeenObjectId); 224 int64_t timestamp = 0; 225 struct timeval tv = {0, 0}; 226 gettimeofday(&tv, nullptr); 227 const int THOUSAND = 1000; 228 timestamp = static_cast<int64_t>(tv.tv_usec + tv.tv_sec * THOUSAND * THOUSAND); 229 lastSeenObjectIdEvent.SetTimestamp(timestamp); 230 channel_->SendNotification(lastSeenObjectIdEvent); 231 } 232 ResetProfiles()233 void HeapProfilerImpl::Frontend::ResetProfiles() 234 { 235 if (!AllowNotify()) { 236 return; 237 } 238 } 239 AddInspectedHeapObject(const AddInspectedHeapObjectParams & params)240 DispatchResponse HeapProfilerImpl::AddInspectedHeapObject([[maybe_unused]] const AddInspectedHeapObjectParams ¶ms) 241 { 242 LOG(ERROR, DEBUGGER) << "AddInspectedHeapObject not support now."; 243 return DispatchResponse::Ok(); 244 } 245 CollectGarbage()246 DispatchResponse HeapProfilerImpl::CollectGarbage() 247 { 248 LOG(ERROR, DEBUGGER) << "CollectGarbage not support now."; 249 return DispatchResponse::Ok(); 250 } 251 Enable()252 DispatchResponse HeapProfilerImpl::Enable() 253 { 254 LOG(ERROR, DEBUGGER) << "Enable not support now."; 255 return DispatchResponse::Ok(); 256 } 257 Disable()258 DispatchResponse HeapProfilerImpl::Disable() 259 { 260 LOG(ERROR, DEBUGGER) << "Disable not support now."; 261 return DispatchResponse::Ok(); 262 } 263 GetHeapObjectId(const GetHeapObjectIdParams & params,HeapSnapshotObjectId * objectId)264 DispatchResponse HeapProfilerImpl::GetHeapObjectId([[maybe_unused]] const GetHeapObjectIdParams ¶ms, 265 HeapSnapshotObjectId *objectId) 266 { 267 ASSERT(objectId != nullptr); 268 *objectId = 0; 269 LOG(ERROR, DEBUGGER) << "GetHeapObjectId not support now."; 270 return DispatchResponse::Ok(); 271 } 272 GetObjectByHeapObjectId(const GetObjectByHeapObjectIdParams & params,std::unique_ptr<RemoteObject> * remoteObjectResult)273 DispatchResponse HeapProfilerImpl::GetObjectByHeapObjectId([[maybe_unused]] const GetObjectByHeapObjectIdParams ¶ms, 274 [[maybe_unused]] std::unique_ptr<RemoteObject> *remoteObjectResult) 275 { 276 LOG(ERROR, DEBUGGER) << "GetObjectByHeapObjectId not support now."; 277 return DispatchResponse::Ok(); 278 } 279 GetSamplingProfile(std::unique_ptr<SamplingHeapProfile> * profile)280 DispatchResponse HeapProfilerImpl::GetSamplingProfile([[maybe_unused]]std::unique_ptr<SamplingHeapProfile> *profile) 281 { 282 LOG(ERROR, DEBUGGER) << "GetSamplingProfile not support now."; 283 return DispatchResponse::Ok(); 284 } 285 StartSampling(const StartSamplingParams & params)286 DispatchResponse HeapProfilerImpl::StartSampling([[maybe_unused]]const StartSamplingParams ¶ms) 287 { 288 LOG(ERROR, DEBUGGER) << "StartSampling not support now."; 289 return DispatchResponse::Ok(); 290 } 291 StartTrackingHeapObjects(const StartTrackingHeapObjectsParams & params)292 DispatchResponse HeapProfilerImpl::StartTrackingHeapObjects( 293 [[maybe_unused]] const StartTrackingHeapObjectsParams ¶ms) 294 { 295 bool result = panda::DFXJSNApi::StartHeapTracking(vm_, INTERVAL, true, &stream_); 296 if (result) { 297 return DispatchResponse::Ok(); 298 } else { 299 return DispatchResponse::Fail("StartHeapTracking fail"); 300 } 301 } 302 StopSampling(std::unique_ptr<SamplingHeapProfile> * profile)303 DispatchResponse HeapProfilerImpl::StopSampling([[maybe_unused]]std::unique_ptr<SamplingHeapProfile> *profile) 304 { 305 LOG(ERROR, DEBUGGER) << "StopSampling not support now."; 306 return DispatchResponse::Ok(); 307 } 308 StopTrackingHeapObjects(const StopTrackingHeapObjectsParams & params)309 DispatchResponse HeapProfilerImpl::StopTrackingHeapObjects(const StopTrackingHeapObjectsParams ¶ms) 310 { 311 bool result = false; 312 if (params.GetReportProgress()) { 313 HeapProfilerProgress progress(&frontend_); 314 result = panda::DFXJSNApi::StopHeapTracking(vm_, &stream_, &progress); 315 } else { 316 result = panda::DFXJSNApi::StopHeapTracking(vm_, &stream_, nullptr); 317 } 318 if (result) { 319 return DispatchResponse::Ok(); 320 } else { 321 return DispatchResponse::Fail("StopHeapTracking fail"); 322 } 323 } 324 TakeHeapSnapshot(const StopTrackingHeapObjectsParams & params)325 DispatchResponse HeapProfilerImpl::TakeHeapSnapshot(const StopTrackingHeapObjectsParams ¶ms) 326 { 327 if (params.GetReportProgress()) { 328 HeapProfilerProgress progress(&frontend_); 329 panda::DFXJSNApi::DumpHeapSnapshot(vm_, 0, &stream_, &progress, true); 330 } else { 331 panda::DFXJSNApi::DumpHeapSnapshot(vm_, 0, &stream_, nullptr, true); 332 } 333 return DispatchResponse::Ok(); 334 } 335 } // namespace panda::ecmascript::tooling 336