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 
22 namespace panda::ecmascript::kungfu {
23 
24 struct CallArgs {
25     GateRef arg0;
26     GateRef arg1;
27     GateRef arg2;
28 };
29 
30 struct CallArgsWithThis {
31     GateRef arg0;
32     GateRef arg1;
33     GateRef arg2;
34     GateRef thisValue;
35 };
36 
37 struct CallArgv {
38     GateRef argc;
39     GateRef argv;
40 };
41 
42 struct CallArgvWithThis {
43     GateRef argc;
44     GateRef argv;
45     GateRef thisValue;
46 };
47 
48 struct SuperCallArgs {
49     GateRef thisFunc;
50     GateRef array;
51     GateRef argc;
52     GateRef argv;
53     GateRef thisObj;
54     GateRef newTarget;
55 };
56 
57 struct CallConstructorArgs {
58     GateRef argc;
59     GateRef argv;
60     GateRef thisObj;
61 };
62 
63 struct CallGetterArgs {
64     GateRef receiver;
65 };
66 
67 struct CallSetterArgs {
68     GateRef receiver;
69     GateRef value;
70 };
71 
72 struct CallThisArg2WithReturnArgs {
73     GateRef thisValue;
74     GateRef arg0;
75     GateRef arg1;
76 };
77 
78 struct CallThisArg3WithReturnArgs {
79     GateRef argHandle;
80     GateRef value;
81     GateRef key;
82     GateRef thisValue;
83 };
84 
85 struct CallThisArgvWithReturnArgs {
86     GateRef argc;
87     GateRef argv;
88     GateRef thisValue;
89 };
90 
91 struct JSCallArgs {
JSCallArgspanda::ecmascript::kungfu::JSCallArgs92     JSCallArgs() {}
JSCallArgspanda::ecmascript::kungfu::JSCallArgs93     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 
110 class CallStubBuilder : public StubBuilder {
111 public:
CallStubBuilder(StubBuilder *parent, GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize, Variable *result, GateRef hotnessCounter, JSCallArgs callArgs, ProfileOperation callback = ProfileOperation(), bool checkIsCallable = true, GateRef hir = Circuit::NullGate())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     }
CallStubBuilder(Environment *env)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 
139 protected:
140 
141 private:
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