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 "agent/profiler_impl.h"
17
18#include "tooling/base/pt_events.h"
19#include "protocol_channel.h"
20#include "ecmascript/debugger/debugger_api.h"
21
22#include "ecmascript/napi/include/dfx_jsnapi.h"
23
24namespace panda::ecmascript::tooling {
25// Whenever adding a new protocol which is not a standard CDP protocol,
26// must add its methodName to the profilerProtocolList
27void ProfilerImpl::InitializeExtendedProtocolsList()
28{
29    std::vector<std::string> profilerProtocolList {
30        "startTypeProfile",
31        "stopTypeProfile",
32        "takeTypeProfile",
33        "enableSerializationTimeoutCheck",
34        "disableSerializationTimeoutCheck"
35    };
36    profilerExtendedProtocols_ = std::move(profilerProtocolList);
37}
38
39void ProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request)
40{
41    Method method = GetMethodEnum(request.GetMethod());
42    LOG_DEBUGGER(DEBUG) << "dispatch [" << request.GetMethod() << "] to ProfilerImpl";
43    switch (method) {
44        case Method::DISABLE:
45            Disable(request);
46            break;
47        case Method::ENABLE:
48            Enable(request);
49            break;
50        case Method::START:
51            Start(request);
52            break;
53        case Method::STOP:
54            Stop(request);
55            break;
56        case Method::SET_SAMPLING_INTERVAL:
57            SetSamplingInterval(request);
58            break;
59        case Method::GET_BEST_EFFORT_COVERAGE:
60            GetBestEffortCoverage(request);
61            break;
62        case Method::STOP_PRECISE_COVERAGE:
63            StopPreciseCoverage(request);
64            break;
65        case Method::TAKE_PRECISE_COVERAGE:
66            TakePreciseCoverage(request);
67            break;
68        case Method::START_PRECISE_COVERAGE:
69            StartPreciseCoverage(request);
70            break;
71        case Method::START_TYPE_PROFILE:
72            StartTypeProfile(request);
73            break;
74        case Method::STOP_TYPE_PROFILE:
75            StopTypeProfile(request);
76            break;
77        case Method::TAKE_TYPE_PROFILE:
78            TakeTypeProfile(request);
79            break;
80        case Method::ENABLE_SERIALIZATION_TIMEOUT_CHECK:
81            EnableSerializationTimeoutCheck(request);
82            break;
83        case Method::DISABLE_SERIALIZATION_TIMEOUT_CHECK:
84            DisableSerializationTimeoutCheck(request);
85            break;
86        default:
87            SendResponse(request, DispatchResponse::Fail("Unknown method: " + request.GetMethod()));
88            break;
89    }
90}
91
92ProfilerImpl::DispatcherImpl::Method ProfilerImpl::DispatcherImpl::GetMethodEnum(const std::string& method)
93{
94    if (method == "disable") {
95        return Method::DISABLE;
96    } else if (method == "enable") {
97        return Method::ENABLE;
98    } else if (method == "start") {
99        return Method::START;
100    } else if (method == "stop") {
101        return Method::STOP;
102    } else if (method == "setSamplingInterval") {
103        return Method::SET_SAMPLING_INTERVAL;
104    } else if (method == "getBestEffortCoverage") {
105        return Method::GET_BEST_EFFORT_COVERAGE;
106    } else if (method == "stopPreciseCoverage") {
107        return Method::STOP_PRECISE_COVERAGE;
108    } else if (method == "takePreciseCoverage") {
109        return Method::TAKE_PRECISE_COVERAGE;
110    } else if (method == "startPreciseCoverage") {
111        return Method::START_PRECISE_COVERAGE;
112    } else if (method == "startTypeProfile") {
113        return Method::START_TYPE_PROFILE;
114    } else if (method == "stopTypeProfile") {
115        return Method::STOP_TYPE_PROFILE;
116    } else if (method == "takeTypeProfile") {
117        return Method::TAKE_TYPE_PROFILE;
118    } else if (method == "enableSerializationTimeoutCheck") {
119        return Method::ENABLE_SERIALIZATION_TIMEOUT_CHECK;
120    } else if (method == "disableSerializationTimeoutCheck") {
121        return Method::DISABLE_SERIALIZATION_TIMEOUT_CHECK;
122    } else {
123        return Method::UNKNOWN;
124    }
125}
126
127void ProfilerImpl::DispatcherImpl::Disable(const DispatchRequest &request)
128{
129    DispatchResponse response = profiler_->Disable();
130    SendResponse(request, response);
131}
132
133void ProfilerImpl::DispatcherImpl::Enable(const DispatchRequest &request)
134{
135    DispatchResponse response = profiler_->Enable();
136    profiler_->InitializeExtendedProtocolsList();
137    EnableReturns result(profiler_->profilerExtendedProtocols_);
138    SendResponse(request, response, result);
139}
140
141void ProfilerImpl::DispatcherImpl::Start(const DispatchRequest &request)
142{
143    DispatchResponse response = profiler_->Start();
144    SendResponse(request, response);
145}
146
147void ProfilerImpl::DispatcherImpl::Stop(const DispatchRequest &request)
148{
149    std::unique_ptr<Profile> profile;
150    DispatchResponse response = profiler_->Stop(&profile);
151    if (profile == nullptr) {
152        SendResponse(request, response);
153        return;
154    }
155
156    StopReturns result(std::move(profile));
157    SendResponse(request, response, result);
158}
159
160void ProfilerImpl::DispatcherImpl::EnableSerializationTimeoutCheck(const DispatchRequest &request)
161{
162    std::unique_ptr<SeriliazationTimeoutCheckEnableParams> params =
163        SeriliazationTimeoutCheckEnableParams::Create(request.GetParams());
164    if (params == nullptr) {
165        SendResponse(request, DispatchResponse::Fail("wrong params"));
166        return;
167    }
168    DispatchResponse response = profiler_->EnableSerializationTimeoutCheck(*params);
169    SendResponse(request, response);
170}
171
172void ProfilerImpl::DispatcherImpl::DisableSerializationTimeoutCheck(const DispatchRequest &request)
173{
174    DispatchResponse response = profiler_->DisableSerializationTimeoutCheck();
175    SendResponse(request, response);
176}
177
178void ProfilerImpl::DispatcherImpl::SetSamplingInterval(const DispatchRequest &request)
179{
180    std::unique_ptr<SetSamplingIntervalParams> params = SetSamplingIntervalParams::Create(request.GetParams());
181    if (params == nullptr) {
182        SendResponse(request, DispatchResponse::Fail("wrong params"));
183        return;
184    }
185    DispatchResponse response = profiler_->SetSamplingInterval(*params);
186    SendResponse(request, response);
187}
188
189void ProfilerImpl::DispatcherImpl::GetBestEffortCoverage(const DispatchRequest &request)
190{
191    DispatchResponse response = profiler_->GetBestEffortCoverage();
192    SendResponse(request, response);
193}
194
195void ProfilerImpl::DispatcherImpl::StopPreciseCoverage(const DispatchRequest &request)
196{
197    DispatchResponse response = profiler_->StopPreciseCoverage();
198    SendResponse(request, response);
199}
200
201void ProfilerImpl::DispatcherImpl::TakePreciseCoverage(const DispatchRequest &request)
202{
203    DispatchResponse response = profiler_->TakePreciseCoverage();
204    SendResponse(request, response);
205}
206
207void ProfilerImpl::DispatcherImpl::StartPreciseCoverage(const DispatchRequest &request)
208{
209    std::unique_ptr<StartPreciseCoverageParams> params = StartPreciseCoverageParams::Create(request.GetParams());
210    if (params == nullptr) {
211        SendResponse(request, DispatchResponse::Fail("wrong params"));
212        return;
213    }
214    DispatchResponse response = profiler_->StartPreciseCoverage(*params);
215    SendResponse(request, response);
216}
217
218void ProfilerImpl::DispatcherImpl::StartTypeProfile(const DispatchRequest &request)
219{
220    DispatchResponse response = profiler_->StartTypeProfile();
221    SendResponse(request, response);
222}
223
224void ProfilerImpl::DispatcherImpl::StopTypeProfile(const DispatchRequest &request)
225{
226    DispatchResponse response = profiler_->StopTypeProfile();
227    SendResponse(request, response);
228}
229
230void ProfilerImpl::DispatcherImpl::TakeTypeProfile(const DispatchRequest &request)
231{
232    DispatchResponse response = profiler_->TakeTypeProfile();
233    SendResponse(request, response);
234}
235
236bool ProfilerImpl::Frontend::AllowNotify() const
237{
238    return channel_ != nullptr;
239}
240
241void ProfilerImpl::Frontend::PreciseCoverageDeltaUpdate()
242{
243    if (!AllowNotify()) {
244        return;
245    }
246
247    tooling::PreciseCoverageDeltaUpdate preciseCoverageDeltaUpdate;
248    channel_->SendNotification(preciseCoverageDeltaUpdate);
249}
250
251DispatchResponse ProfilerImpl::Disable()
252{
253    return DispatchResponse::Ok();
254}
255
256DispatchResponse ProfilerImpl::Enable()
257{
258    return DispatchResponse::Ok();
259}
260
261DispatchResponse ProfilerImpl::Start()
262{
263    panda::JSNApi::SetProfilerState(vm_, true);
264    bool result = panda::DFXJSNApi::StartCpuProfilerForInfo(vm_);
265    if (!result) {
266        LOG_DEBUGGER(ERROR) << "ProfilerImpl::Start failed";
267        return DispatchResponse::Fail("Start is failure");
268    }
269    return DispatchResponse::Ok();
270}
271
272DispatchResponse ProfilerImpl::Stop(std::unique_ptr<Profile> *profile)
273{
274    auto profileInfo = panda::DFXJSNApi::StopCpuProfilerForInfo(vm_);
275    if (profileInfo == nullptr) {
276        LOG_DEBUGGER(ERROR) << "Transfer DFXJSNApi::StopCpuProfilerImpl is failure";
277        return DispatchResponse::Fail("Stop is failure");
278    }
279    *profile = Profile::FromProfileInfo(*profileInfo);
280    panda::JSNApi::SetProfilerState(vm_, false);
281    return DispatchResponse::Ok();
282}
283
284DispatchResponse ProfilerImpl::EnableSerializationTimeoutCheck(const SeriliazationTimeoutCheckEnableParams &params)
285{
286    int32_t threshhold = params.GetThreshold();
287    panda::DFXJSNApi::EnableSeriliazationTimeoutCheck(vm_, threshhold);
288    LOG_DEBUGGER(DEBUG) << "Profiler Serialization timeout check is enabled with threshhold: " << threshhold;
289    return DispatchResponse::Ok();
290}
291
292DispatchResponse ProfilerImpl::DisableSerializationTimeoutCheck()
293{
294    panda::DFXJSNApi::DisableSeriliazationTimeoutCheck(vm_);
295    LOG_DEBUGGER(DEBUG) << "Profiler Serialization check is disabled";
296    return DispatchResponse::Ok();
297}
298
299DispatchResponse ProfilerImpl::SetSamplingInterval(const SetSamplingIntervalParams &params)
300{
301    panda::DFXJSNApi::SetCpuSamplingInterval(vm_, params.GetInterval());
302    return DispatchResponse::Ok();
303}
304
305DispatchResponse ProfilerImpl::GetBestEffortCoverage()
306{
307    return DispatchResponse::Fail("GetBestEffortCoverage not support now");
308}
309
310DispatchResponse ProfilerImpl::StopPreciseCoverage()
311{
312    return DispatchResponse::Fail("StopPreciseCoverage not support now");
313}
314
315DispatchResponse ProfilerImpl::TakePreciseCoverage()
316{
317    return DispatchResponse::Fail("TakePreciseCoverage not support now");
318}
319
320DispatchResponse ProfilerImpl::StartPreciseCoverage([[maybe_unused]] const StartPreciseCoverageParams &params)
321{
322    return DispatchResponse::Fail("StartPreciseCoverage not support now");
323}
324
325DispatchResponse ProfilerImpl::StartTypeProfile()
326{
327    return DispatchResponse::Fail("StartTypeProfile not support now");
328}
329
330DispatchResponse ProfilerImpl::StopTypeProfile()
331{
332    return DispatchResponse::Fail("StopTypeProfile not support now");
333}
334
335DispatchResponse ProfilerImpl::TakeTypeProfile()
336{
337    return DispatchResponse::Fail("TakeTypeProfile not support now");
338}
339}  // namespace panda::ecmascript::tooling
340