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 
24 namespace panda::ecmascript::kungfu {
25 enum 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 
40 using 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 
46 using Callback = std::function<void(const std::initializer_list<GateRef> &, OperationType)>;
47 class ProfileOperation {
48 public:
ProfileOperation()49     ProfileOperation() : callback_(nullptr), jitCallback_(nullptr) {}
ProfileOperation(Callback callback, Callback jitCallback)50     explicit ProfileOperation(Callback callback, Callback jitCallback) : callback_(callback),
51         jitCallback_(jitCallback) {}
52 
IsEmpty() const53     inline bool IsEmpty() const
54     {
55         return callback_ == nullptr;
56     }
57 
IsJitEmpty() const58     inline bool IsJitEmpty() const
59     {
60         return jitCallback_ == nullptr;
61     }
62 
ProfileCall(GateRef func) const63     inline void ProfileCall(GateRef func) const
64     {
65         if (callback_) {
66             callback_({ func }, OperationType::CALL);
67         }
68     }
69 
ProfileNativeCall(GateRef func) const70     inline void ProfileNativeCall(GateRef func) const
71     {
72         if (callback_) {
73             callback_({ func }, OperationType::NATIVE_CALL);
74         }
75     }
76 
ProfileGetterSetterCall(GateRef func) const77     inline void ProfileGetterSetterCall(GateRef func) const
78     {
79         if (callback_) {
80             callback_({ func }, OperationType::GETTER_SETTER_CALL);
81         }
82     }
83 
ProfileOpType(GateRef type) const84     inline void ProfileOpType(GateRef type) const
85     {
86         if (callback_) {
87             callback_({ type }, OperationType::OPERATION_TYPE);
88         }
89     }
90 
91     template <typename TypeCombine>
ProfileCombineOpType(GateRef curType, GateRef type, TypeCombine combine) const92     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 
ProfileDefineClass(GateRef constructor) const100     inline void ProfileDefineClass(GateRef constructor) const
101     {
102         if (callback_) {
103             callback_({ constructor }, OperationType::DEFINE_CLASS);
104         }
105     }
106 
ProfileCreateObject(GateRef newObj) const107     inline void ProfileCreateObject(GateRef newObj) const
108     {
109         if (callback_) {
110             callback_({ newObj }, OperationType::CREATE_OBJECT);
111         }
112     }
113 
TryDump() const114     inline void TryDump() const
115     {
116         if (callback_) {
117             callback_({ }, OperationType::TRY_DUMP);
118         }
119     }
120 
TryJitCompile() const121     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 
TryPreDump() const130     inline void TryPreDump() const
131     {
132         if (callback_) {
133             callback_({ }, OperationType::TRY_PREDUMP);
134         }
135     }
136 
ProfileBranch(bool isTrue) const137     inline void ProfileBranch(bool isTrue) const
138     {
139         if (callback_) {
140             callback_({}, isTrue ? OperationType::TRUE_BRANCH : OperationType::FALSE_BRANCH);
141         }
142     }
143 
ProfileGetIterator(GateRef iterator) const144     inline void ProfileGetIterator(GateRef iterator) const
145     {
146         if (callback_) {
147             callback_({ iterator }, OperationType::ITERATOR_FUNC_KIND);
148         }
149     }
150 
151 private:
152     Callback callback_;
153     Callback jitCallback_;
154 };
155 } // namespace panda::ecmascript::kungfu
156 #endif // ECMASCRIPT_COMPILER_PROFILER_OPERATION_H
157