1/*
2 * Copyright (c) 2024 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_CALL_STUB_BUILDER_H
17#define ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H
18
19#include "ecmascript/compiler/profiler_operation.h"
20#include "ecmascript/compiler/stub_builder.h"
21
22namespace panda::ecmascript::kungfu {
23
24struct CallArgs {
25    GateRef arg0;
26    GateRef arg1;
27    GateRef arg2;
28};
29
30struct CallArgsWithThis {
31    GateRef arg0;
32    GateRef arg1;
33    GateRef arg2;
34    GateRef thisValue;
35};
36
37struct CallArgv {
38    GateRef argc;
39    GateRef argv;
40};
41
42struct CallArgvWithThis {
43    GateRef argc;
44    GateRef argv;
45    GateRef thisValue;
46};
47
48struct SuperCallArgs {
49    GateRef thisFunc;
50    GateRef array;
51    GateRef argc;
52    GateRef argv;
53    GateRef thisObj;
54    GateRef newTarget;
55};
56
57struct CallConstructorArgs {
58    GateRef argc;
59    GateRef argv;
60    GateRef thisObj;
61};
62
63struct CallGetterArgs {
64    GateRef receiver;
65};
66
67struct CallSetterArgs {
68    GateRef receiver;
69    GateRef value;
70};
71
72struct CallThisArg2WithReturnArgs {
73    GateRef thisValue;
74    GateRef arg0;
75    GateRef arg1;
76};
77
78struct CallThisArg3WithReturnArgs {
79    GateRef argHandle;
80    GateRef value;
81    GateRef key;
82    GateRef thisValue;
83};
84
85struct CallThisArgvWithReturnArgs {
86    GateRef argc;
87    GateRef argv;
88    GateRef thisValue;
89};
90
91struct JSCallArgs {
92    JSCallArgs() {}
93    JSCallArgs(JSCallMode m) : mode(m) {}
94    JSCallMode mode {JSCallMode::CALL_ARG0};
95    union {
96        CallArgs callArgs;
97        CallArgsWithThis callArgsWithThis;
98        CallArgv callArgv;
99        CallArgvWithThis callArgvWithThis;
100        SuperCallArgs superCallArgs;
101        CallConstructorArgs callConstructorArgs;
102        CallGetterArgs callGetterArgs;
103        CallSetterArgs callSetterArgs;
104        CallThisArg2WithReturnArgs callThisArg2WithReturnArgs;
105        CallThisArg3WithReturnArgs callThisArg3WithReturnArgs;
106        CallThisArgvWithReturnArgs callThisArgvWithReturnArgs;
107    };
108};
109
110class CallStubBuilder : public StubBuilder {
111public:
112    explicit CallStubBuilder(StubBuilder *parent, GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize,
113                             Variable *result, GateRef hotnessCounter, JSCallArgs callArgs,
114                             ProfileOperation callback = ProfileOperation(),
115                             bool checkIsCallable = true, GateRef hir = Circuit::NullGate())
116        : StubBuilder(parent)
117    {
118        this->glue_ = glue;
119        this->func_ = func;
120        this->jumpSize_ = jumpSize;
121        this->actualNumArgs_ = actualNumArgs;
122        this->result_ = result;
123        this->hotnessCounter_ = hotnessCounter;
124        this->callArgs_ = callArgs;
125        this->callback_ = callback;
126        this->checkIsCallable_ = checkIsCallable;
127        this->hir_ = hir;
128    }
129    explicit CallStubBuilder(Environment *env)
130        : StubBuilder(env) {}
131    ~CallStubBuilder() override = default;
132    NO_MOVE_SEMANTIC(CallStubBuilder);
133    NO_COPY_SEMANTIC(CallStubBuilder);
134    void GenerateCircuit() override {}
135
136    void JSCallDispatchForBaseline(Label *exit, Label *noNeedCheckException = nullptr);
137    GateRef JSCallDispatch();
138
139protected:
140
141private:
142    GateRef glue_ {0};
143    GateRef func_ {0};
144    GateRef jumpSize_ {0};
145    GateRef actualNumArgs_ {0};
146    GateRef hotnessCounter_ {0};
147    Variable *result_ {nullptr};
148    JSCallArgs callArgs_;
149    ProfileOperation callback_;
150    bool checkIsCallable_ {true};
151    GateRef hir_ {0};
152
153    bool isFast_ {true};
154    bool isBridge_ {false};
155    bool isForBaseline_ {false};
156    GateRef sp_ {0};
157    GateRef method_ {0};
158    GateRef numArgs_ {0};
159    GateRef bitfield_ {0};
160    GateRef callField_ {0};
161    GateRef newTarget_ {0};
162    GateRef thisValue_ {0};
163    GateRef nativeCode_ {0};
164    GateRef realNumArgs_ {0};
165    GateRef isNativeMask_ {0};
166    GateRef baselineBuiltinFp_ {0};
167
168    void JSCallInit(Label *exit, Label *funcIsHeapObject, Label *funcIsCallable, Label *funcNotCallable);
169    void JSCallNative(Label *exit);
170    void JSCallJSFunction(Label *exit, Label *noNeedCheckException = nullptr);
171    void JSFastAotCall(Label *exit);
172    void JSSlowAotCall(Label *exit);
173    GateRef CallConstructorBridge(const int idxForAot, const std::vector<GateRef> &argsForAot);
174    void CallBridge(GateRef code, GateRef expectedNum, Label *exit);
175    void JSCallAsmInterpreter(bool hasBaselineCode, Label *methodNotAot, Label *exit, Label *noNeedCheckException);
176
177    int PrepareIdxForNative();
178    std::vector<GateRef> PrepareArgsForNative();
179    std::vector<GateRef> PrepareBasicArgsForNative();
180    std::vector<GateRef> PrepareAppendArgsForNative();
181
182    int PrepareIdxForAot();
183    std::vector<GateRef> PrepareArgsForAot(GateRef expectedNum);
184    std::vector<GateRef> PrepareBasicArgsForAot();
185    std::vector<GateRef> PrepareAppendArgsForAotStep1();
186    std::vector<GateRef> PrepareAppendArgsForAotStep2();
187    std::vector<GateRef> PrepareAppendArgsForAotStep3(GateRef expectedNum);
188
189    int PrepareIdxForAsmInterpreterForBaselineWithBaselineCode();
190    int PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode();
191    int PrepareIdxForAsmInterpreterWithBaselineCode();
192    int PrepareIdxForAsmInterpreterWithoutBaselineCode();
193    std::vector<GateRef> PrepareArgsForAsmInterpreter();
194    std::vector<GateRef> PrepareBasicArgsForAsmInterpreter();
195    std::vector<GateRef> PrepareAppendArgsForAsmInterpreter();
196
197    void CallFastBuiltin(Label* notFastBuiltins, Label *exit);
198    std::vector<GateRef> PrepareArgsForFastBuiltin();
199    std::vector<GateRef> PrepareBasicArgsForFastBuiltin();
200    std::vector<GateRef> PrepareAppendArgsForFastBuiltin();
201    bool IsCallModeSupportPGO() const;
202    bool IsCallModeSupportCallBuiltin() const;
203    bool IsSlowAotCall() const;
204    bool IsFastAotCall() const;
205    bool IsSlowAotCallWithBridge() const;
206    bool IsFastAotCallWithBridge() const;
207    bool CheckResultValueChangedWithReturn(GateRef prevResRef) const;
208    void HandleProfileCall();
209    void HandleProfileNativeCall();
210    bool IsCallModeGetterSetter();
211};
212
213}   // panda::ecmascript::kungfu
214#endif  // ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H