1/*
2 * Copyright (c) 2021-2023 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_DFX_VMSTAT_CALLER_STAT_H
17#define ECMASCRIPT_DFX_VMSTAT_CALLER_STAT_H
18
19#include <cstdint>
20#include <cstring>
21#include <ctime>
22
23#include "ecmascript/mem/c_string.h"
24
25#include "libpandabase/macros.h"
26
27namespace panda::ecmascript {
28class EcmaRuntimeStat;
29class PandaRuntimeCallerStat {
30public:
31    // NOLINTNEXTLINE(modernize-pass-by-value)
32    explicit PandaRuntimeCallerStat(const CString &name) : name_(name) {}
33    PandaRuntimeCallerStat() = default;
34    virtual ~PandaRuntimeCallerStat() = default;
35
36    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PandaRuntimeCallerStat);
37    DEFAULT_COPY_SEMANTIC(PandaRuntimeCallerStat);
38
39    void UpdateState(uint64_t elapsed)
40    {
41        totalCount_++;
42        totalTime_ += elapsed;
43        maxTime_ = elapsed < maxTime_ ? maxTime_ : elapsed;
44    }
45    const char *Name() const
46    {
47        return name_.c_str();
48    }
49    CString GetHeaderOfName() const
50    {
51        CString::size_type index = name_.find_first_of("::");
52        if (index == CString::npos) {
53            return CString("");
54        }
55        CString header = name_.substr(0, index);
56        return header;
57    }
58    uint64_t TotalCount() const
59    {
60        return totalCount_;
61    }
62    uint64_t TotalTime() const
63    {
64        return totalTime_;
65    }
66    uint64_t MaxTime() const
67    {
68        return maxTime_;
69    }
70
71    void Reset()
72    {
73        totalCount_ = 0;
74        totalTime_ = 0;
75        maxTime_ = 0;
76    }
77
78private:
79    CString name_ {};
80    uint64_t totalCount_ {0};
81    uint64_t totalTime_ {0};
82    uint64_t maxTime_ {0};
83};
84
85class PandaRuntimeTimer {
86public:
87    void Start(PandaRuntimeCallerStat *callerStat, PandaRuntimeTimer *parent);
88    inline static uint64_t Now()
89    {
90        struct timespec timeNow = {0, 0};
91        clock_gettime(CLOCK_REALTIME, &timeNow);
92        return timeNow.tv_sec * NANOSECONDSINSECOND + timeNow.tv_nsec;
93    }
94
95    uint64_t Elapsed() const
96    {
97        return elapsed_;
98    }
99
100    inline bool IsStarted() const
101    {
102        return start_ != 0;
103    }
104
105    inline void SetParent(PandaRuntimeTimer *parent)
106    {
107        parent_ = parent;
108    }
109
110    void Snapshot();
111
112    inline void UpdateCallerState()
113    {
114        callerStat_->UpdateState(elapsed_);
115    }
116
117private:
118    static constexpr uint64_t NANOSECONDSINSECOND = 1000000000;
119    PandaRuntimeTimer *Stop();
120    void Pause(uint64_t now);
121    void Resume(uint64_t now);
122    PandaRuntimeCallerStat *callerStat_ {nullptr};
123    PandaRuntimeTimer *parent_ {nullptr};
124    uint64_t start_ {0};
125    uint64_t elapsed_ {0};
126
127    friend class EcmaRuntimeStat;
128    friend class FunctionCallTimer;
129};
130}  // namespace panda::ecmascript
131#endif // ECMASCRIPT_DFX_VMSTAT_CALLER_STAT_H
132