1/*
2 * Copyright (c) 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_COMPILER_PROFILER_OPERATION_H
17#define ECMASCRIPT_COMPILER_PROFILER_OPERATION_H
18
19#include <functional>
20#include <initializer_list>
21
22#include "ecmascript/compiler/share_gate_meta_data.h"
23
24namespace panda::ecmascript::kungfu {
25enum class OperationType : uint8_t {
26    CALL,
27    NATIVE_CALL,
28    GETTER_SETTER_CALL,
29    OPERATION_TYPE,
30    DEFINE_CLASS,
31    CREATE_OBJECT,
32    TRUE_BRANCH,
33    FALSE_BRANCH,
34    TRY_DUMP,
35    TRY_PREDUMP,
36    ITERATOR_FUNC_KIND,
37    TRY_JIT,
38};
39
40using SlotIDFormat = BytecodeInstruction::Format;
41
42#define COMBINE_TYPE_CALL_BACK(curType, type) \
43    callback.ProfileCombineOpType(            \
44        *(curType), type, [this](GateRef curType, GateRef type)->GateRef{ return Int64Or(curType, type); })
45
46using Callback = std::function<void(const std::initializer_list<GateRef> &, OperationType)>;
47class ProfileOperation {
48public:
49    ProfileOperation() : callback_(nullptr), jitCallback_(nullptr) {}
50    explicit ProfileOperation(Callback callback, Callback jitCallback) : callback_(callback),
51        jitCallback_(jitCallback) {}
52
53    inline bool IsEmpty() const
54    {
55        return callback_ == nullptr;
56    }
57
58    inline bool IsJitEmpty() const
59    {
60        return jitCallback_ == nullptr;
61    }
62
63    inline void ProfileCall(GateRef func) const
64    {
65        if (callback_) {
66            callback_({ func }, OperationType::CALL);
67        }
68    }
69
70    inline void ProfileNativeCall(GateRef func) const
71    {
72        if (callback_) {
73            callback_({ func }, OperationType::NATIVE_CALL);
74        }
75    }
76
77    inline void ProfileGetterSetterCall(GateRef func) const
78    {
79        if (callback_) {
80            callback_({ func }, OperationType::GETTER_SETTER_CALL);
81        }
82    }
83
84    inline void ProfileOpType(GateRef type) const
85    {
86        if (callback_) {
87            callback_({ type }, OperationType::OPERATION_TYPE);
88        }
89    }
90
91    template <typename TypeCombine>
92    inline void ProfileCombineOpType(GateRef curType, GateRef type, TypeCombine combine) const
93    {
94        if (callback_) {
95            GateRef ret = combine(curType, type);
96            callback_({ ret }, OperationType::OPERATION_TYPE);
97        }
98    }
99
100    inline void ProfileDefineClass(GateRef constructor) const
101    {
102        if (callback_) {
103            callback_({ constructor }, OperationType::DEFINE_CLASS);
104        }
105    }
106
107    inline void ProfileCreateObject(GateRef newObj) const
108    {
109        if (callback_) {
110            callback_({ newObj }, OperationType::CREATE_OBJECT);
111        }
112    }
113
114    inline void TryDump() const
115    {
116        if (callback_) {
117            callback_({ }, OperationType::TRY_DUMP);
118        }
119    }
120
121    inline void TryJitCompile() const
122    {
123        if (callback_) {
124            callback_({ }, OperationType::TRY_JIT);
125        } else if (jitCallback_) {
126            jitCallback_({ }, OperationType::TRY_JIT);
127        }
128    }
129
130    inline void TryPreDump() const
131    {
132        if (callback_) {
133            callback_({ }, OperationType::TRY_PREDUMP);
134        }
135    }
136
137    inline void ProfileBranch(bool isTrue) const
138    {
139        if (callback_) {
140            callback_({}, isTrue ? OperationType::TRUE_BRANCH : OperationType::FALSE_BRANCH);
141        }
142    }
143
144    inline void ProfileGetIterator(GateRef iterator) const
145    {
146        if (callback_) {
147            callback_({ iterator }, OperationType::ITERATOR_FUNC_KIND);
148        }
149    }
150
151private:
152    Callback callback_;
153    Callback jitCallback_;
154};
155} // namespace panda::ecmascript::kungfu
156#endif // ECMASCRIPT_COMPILER_PROFILER_OPERATION_H
157