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#ifndef ECMASCRIPT_COMPILER_INTERPRETER_STUB_H
17#define ECMASCRIPT_COMPILER_INTERPRETER_STUB_H
18
19#include "ecmascript/base/config.h"
20#include "ecmascript/compiler/bc_call_signature.h"
21#include "ecmascript/compiler/profiler_operation.h"
22#include "ecmascript/compiler/rt_call_signature.h"
23#include "ecmascript/compiler/stub_builder.h"
24#include "ecmascript/compiler/circuit_builder-inl.h"
25
26namespace panda::ecmascript::kungfu {
27class StringIdInfo {
28public:
29    enum class Offset : uint8_t {
30        BYTE_0,
31        BYTE_1,
32        BYTE_2,
33        INVALID,
34    };
35    enum class Length : uint8_t {
36        BITS_16,
37        BITS_32,
38        INVALID,
39    };
40    enum class StringIdType : uint8_t {
41        STRING_ID,
42        STRING_ID_INFO,
43    };
44
45    StringIdInfo() : constpool(0), pc(0), offset(Offset::INVALID),
46          length(Length::INVALID), stringId(0), stringIdType(StringIdType::STRING_ID_INFO) {}
47
48    StringIdInfo(GateRef inputConstpool, GateRef inputPc, Offset inputOffset, Length inputLength)
49        : constpool(inputConstpool), pc(inputPc), offset(inputOffset),
50          length(inputLength), stringId(0), stringIdType(StringIdType::STRING_ID_INFO) {}
51
52    explicit StringIdInfo(GateRef inputConstpool, GateRef inputStringId)
53        : constpool(inputConstpool), pc(0), offset(Offset::INVALID),
54          length(Length::INVALID), stringId(inputStringId), stringIdType(StringIdType::STRING_ID) {}
55
56    GateRef GetConstantPool() const
57    {
58        return constpool;
59    }
60
61    GateRef GetPc() const
62    {
63        return pc;
64    }
65
66    Offset GetOffset() const
67    {
68        return offset;
69    }
70
71    Length GetLength() const
72    {
73        return length;
74    }
75
76    GateRef GetStringId() const
77    {
78        return stringId;
79    }
80
81    StringIdType GetStringIdType() const
82    {
83        return stringIdType;
84    }
85
86    bool IsValid() const
87    {
88        if (stringIdType == StringIdType::STRING_ID_INFO) {
89            return (constpool != 0) && (pc != 0) && (offset != Offset::INVALID) && (length != Length::INVALID);
90        }
91        return stringId != 0;
92    }
93
94private:
95    GateRef constpool { 0 };
96    GateRef pc { 0 };
97    Offset offset { Offset::INVALID };
98    Length length { Length::INVALID };
99    GateRef stringId { 0 };
100    StringIdType stringIdType { StringIdType::STRING_ID_INFO };
101};
102
103class InterpreterStubBuilder : public StubBuilder {
104public:
105    InterpreterStubBuilder(CallSignature *callSignature, Environment *env)
106        : StubBuilder(callSignature, env) {}
107    ~InterpreterStubBuilder() override = default;
108    NO_MOVE_SEMANTIC(InterpreterStubBuilder);
109    NO_COPY_SEMANTIC(InterpreterStubBuilder);
110    virtual void GenerateCircuit() override = 0;
111
112    inline void SetVregValue(GateRef glue, GateRef sp, GateRef idx, GateRef val);
113    inline GateRef GetVregValue(GateRef sp, GateRef idx);
114    inline GateRef ReadInst4_0(GateRef pc);
115    inline GateRef ReadInst4_1(GateRef pc);
116    inline GateRef ReadInst4_2(GateRef pc);
117    inline GateRef ReadInst4_3(GateRef pc);
118    inline GateRef ReadInst8_0(GateRef pc);
119    inline GateRef ReadInst8_1(GateRef pc);
120    inline GateRef ReadInst8_2(GateRef pc);
121    inline GateRef ReadInst8_3(GateRef pc);
122    inline GateRef ReadInst8_4(GateRef pc);
123    inline GateRef ReadInst8_5(GateRef pc);
124    inline GateRef ReadInst8_6(GateRef pc);
125    inline GateRef ReadInst8_7(GateRef pc);
126    inline GateRef ReadInst8_8(GateRef pc);
127    inline GateRef ReadInst8_9(GateRef pc);
128    inline GateRef ReadInst16_0(GateRef pc);
129    inline GateRef ReadInst16_1(GateRef pc);
130    inline GateRef ReadInst16_2(GateRef pc);
131    inline GateRef ReadInst16_3(GateRef pc);
132    inline GateRef ReadInst16_4(GateRef pc);
133    inline GateRef ReadInst16_5(GateRef pc);
134    inline GateRef ReadInst16_6(GateRef pc);
135    inline GateRef ReadInst16_7(GateRef pc);
136    inline GateRef ReadInstSigned8_0(GateRef pc);
137    inline GateRef ReadInstSigned16_0(GateRef pc);
138    inline GateRef ReadInstSigned32_0(GateRef pc);
139    inline GateRef ReadInst32_0(GateRef pc);
140    inline GateRef ReadInst32_1(GateRef pc);
141    inline GateRef ReadInst32_2(GateRef pc);
142    inline GateRef ReadInst64_0(GateRef pc);
143
144    inline GateRef GetFrame(GateRef frame);
145    inline GateRef GetCurrentSpFrame(GateRef glue);
146    inline GateRef GetLastLeaveFrame(GateRef glue);
147    inline GateRef GetCurrentFrame(GateRef glue);
148    inline GateRef GetPcFromFrame(GateRef frame);
149    inline GateRef GetCallSizeFromFrame(GateRef frame);
150    inline GateRef GetFunctionFromFrame(GateRef frame);
151    inline GateRef GetNewTarget(GateRef sp);
152    inline GateRef GetThisFromFrame(GateRef frame);
153    inline GateRef GetAccFromFrame(GateRef frame);
154    inline GateRef GetEnvFromFrame(GateRef frame);
155    inline GateRef GetEnvFromFunction(GateRef frame);
156    inline GateRef GetConstpoolFromMethod(GateRef function);
157    inline GateRef GetModule(GateRef sp);
158    inline GateRef GetProfileTypeInfoFromFunction(GateRef function);
159    inline GateRef GetModuleFromFunction(GateRef function);
160    inline GateRef GetSendableEnvFromModule(GateRef function);
161    inline GateRef GetHomeObjectFromFunction(GateRef function);
162    inline GateRef GetResumeModeFromGeneratorObject(GateRef obj);
163    inline GateRef GetResumeModeFromAsyncGeneratorObject(GateRef obj);
164    inline GateRef GetHotnessCounterFromMethod(GateRef method);
165
166    inline void SetCurrentSpFrame(GateRef glue, GateRef sp);
167    inline void SetLastLeaveFrame(GateRef glue, GateRef sp);
168    inline void SetPcToFrame(GateRef glue, GateRef frame, GateRef value);
169    inline void SetCallSizeToFrame(GateRef glue, GateRef frame, GateRef value);
170    inline void SetFunctionToFrame(GateRef glue, GateRef frame, GateRef value);
171    inline void SetAccToFrame(GateRef glue, GateRef frame, GateRef value);
172    inline void SetEnvToFrame(GateRef glue, GateRef frame, GateRef value);
173    inline void SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value);
174    inline void SetFrameState(GateRef glue, GateRef sp, GateRef function, GateRef acc,
175                              GateRef env, GateRef pc, GateRef prev, GateRef type);
176
177    inline void UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
178                                                    GateRef profileTypeInfo, GateRef slotId);
179
180    inline void CheckException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
181		               GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
182			       GateRef res, GateRef offset);
183    inline void CheckPendingException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
184		                      GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
185			              GateRef res, GateRef offset);
186    inline void CheckExceptionWithJump(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
187		                       GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
188			               GateRef res, Label *jump);
189    inline void CheckExceptionWithVar(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
190		                      GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
191			              GateRef res, GateRef offset);
192
193    inline GateRef CheckStackOverflow(GateRef glue, GateRef sp);
194    inline GateRef PushArg(GateRef glue, GateRef sp, GateRef value);
195    inline GateRef PushUndefined(GateRef glue, GateRef sp, GateRef num);
196    inline GateRef PushRange(GateRef glue, GateRef sp, GateRef array, GateRef startIndex, GateRef endIndex);
197    inline GateRef GetStartIdxAndNumArgs(GateRef sp, GateRef restIdx);
198    inline void Dispatch(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
199                         GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter, GateRef format);
200    inline void DispatchWithId(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
201                               GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter, GateRef index);
202    inline void DispatchLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
203                             GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter);
204    inline void DispatchDebugger(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
205                                 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter);
206    inline void DispatchDebuggerLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
207                                     GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter);
208
209    template <bool needPrint>
210    void DebugPrintInstruction();
211private:
212    template<typename... Args>
213    void DispatchBase(GateRef target, GateRef glue, Args... args);
214};
215
216class InterpreterToolsStubBuilder : private InterpreterStubBuilder {
217public:
218    InterpreterToolsStubBuilder(CallSignature *callSignature, Environment *env)
219        : InterpreterStubBuilder(callSignature, env) {}
220    ~InterpreterToolsStubBuilder() override = default;
221    NO_MOVE_SEMANTIC(InterpreterToolsStubBuilder);
222    NO_COPY_SEMANTIC(InterpreterToolsStubBuilder);
223    void GenerateCircuit() override {}
224
225    inline GateRef GetStringId(const StringIdInfo &info);
226};
227
228#define DECLARE_HANDLE_STUB_CLASS(name)                                                         \
229    class name##StubBuilder : public InterpreterStubBuilder {                                   \
230    public:                                                                                     \
231        explicit name##StubBuilder(CallSignature *callSignature, Environment *env)              \
232            : InterpreterStubBuilder(callSignature, env)                                        \
233        {                                                                                       \
234            env->GetCircuit()->SetFrameType(FrameType::ASM_INTERPRETER_FRAME);                  \
235        }                                                                                       \
236        ~name##StubBuilder() = default;                                                         \
237        NO_MOVE_SEMANTIC(name##StubBuilder);                                                    \
238        NO_COPY_SEMANTIC(name##StubBuilder);                                                    \
239        void GenerateCircuit() override;                                                        \
240                                                                                                \
241    protected:                                                                                  \
242        void GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,       \
243                                 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,  \
244                                 ProfileOperation callback);                                    \
245    };
246    INTERPRETER_BC_STUB_LIST(DECLARE_HANDLE_STUB_CLASS)
247    ASM_INTERPRETER_BC_HELPER_STUB_LIST(DECLARE_HANDLE_STUB_CLASS)
248
249#define DECLARE_HANDLE_PROFILE_STUB_CLASS(name, base, ...)                         \
250    class name##StubBuilder : public base##StubBuilder {                           \
251    public:                                                                        \
252        explicit name##StubBuilder(CallSignature *callSignature, Environment *env) \
253            : base##StubBuilder(callSignature, env)                                \
254        {                                                                          \
255        }                                                                          \
256        ~name##StubBuilder() = default;                                            \
257        NO_MOVE_SEMANTIC(name##StubBuilder);                                       \
258        NO_COPY_SEMANTIC(name##StubBuilder);                                       \
259        void GenerateCircuit() override;                                           \
260    };
261    ASM_INTERPRETER_BC_PROFILER_STUB_LIST(DECLARE_HANDLE_PROFILE_STUB_CLASS)
262#undef DECLARE_HANDLE_PROFILE_STUB_CLASS
263#define DECLARE_HANDLE_JIT_PROFILE_STUB_CLASS(name, base, ...)                     \
264    class name##StubBuilder : public base##StubBuilder {                           \
265    public:                                                                        \
266        explicit name##StubBuilder(CallSignature *callSignature, Environment *env) \
267            : base##StubBuilder(callSignature, env)                                \
268        {                                                                          \
269        }                                                                          \
270        ~name##StubBuilder() = default;                                            \
271        NO_MOVE_SEMANTIC(name##StubBuilder);                                       \
272        NO_COPY_SEMANTIC(name##StubBuilder);                                       \
273        void GenerateCircuit() override;                                           \
274    };
275    ASM_INTERPRETER_BC_JIT_PROFILER_STUB_LIST(DECLARE_HANDLE_JIT_PROFILE_STUB_CLASS)
276#undef DECLARE_HANDLE_PROFILE_STUB_CLASS
277#undef DECLARE_HANDLE_STUB_CLASS
278}  // namespace panda::ecmascript::kungfu
279#endif  // ECMASCRIPT_COMPILER_INTERPRETER_STUB_H
280