• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstddef>
20 #include "ecmascript/compiler/profiler_operation.h"
21 #include "ecmascript/compiler/stub_builder.h"
22 
23 namespace panda::ecmascript::kungfu {
24 
25 struct CallArgs {
26     GateRef arg0;
27     GateRef arg1;
28     GateRef arg2;
29 };
30 
31 struct CallArgsWithThis {
32     GateRef arg0;
33     GateRef arg1;
34     GateRef arg2;
35     GateRef thisValue;
36 };
37 
38 struct CallArgv {
39     GateRef argc;
40     GateRef argv;
41 };
42 
43 struct CallArgvWithThis {
44     GateRef argc;
45     GateRef argv;
46     GateRef thisValue;
47 };
48 
49 struct SuperCallArgs {
50     GateRef thisFunc;
51     GateRef array;
52     GateRef argc;
53     GateRef argv;
54     GateRef thisObj;
55     GateRef newTarget;
56 };
57 
58 struct CallConstructorArgs {
59     GateRef argc;
60     GateRef argv;
61     GateRef thisObj;
62 };
63 
64 struct CallGetterArgs {
65     GateRef receiver;
66 };
67 
68 struct CallSetterArgs {
69     GateRef receiver;
70     GateRef value;
71 };
72 
73 struct CallThisArg2WithReturnArgs {
74     GateRef thisValue;
75     GateRef arg0;
76     GateRef arg1;
77 };
78 
79 struct CallThisArg3WithReturnArgs {
80     GateRef argHandle;
81     GateRef value;
82     GateRef key;
83     GateRef thisValue;
84 };
85 
86 struct CallThisArgvWithReturnArgs {
87     GateRef argc;
88     GateRef argv;
89     GateRef thisValue;
90 };
91 
92 struct JSCallArgs {
JSCallArgsJSCallArgs93     JSCallArgs() {}
JSCallArgsJSCallArgs94     JSCallArgs(JSCallMode m) : mode(m) {}
95     JSCallMode mode {JSCallMode::CALL_ARG0};
96     union {
97         CallArgs callArgs;
98         CallArgsWithThis callArgsWithThis;
99         CallArgv callArgv;
100         CallArgvWithThis callArgvWithThis;
101         SuperCallArgs superCallArgs;
102         CallConstructorArgs callConstructorArgs;
103         CallGetterArgs callGetterArgs;
104         CallSetterArgs callSetterArgs;
105         CallThisArg2WithReturnArgs callThisArg2WithReturnArgs;
106         CallThisArg3WithReturnArgs callThisArg3WithReturnArgs;
107         CallThisArgvWithReturnArgs callThisArgvWithReturnArgs;
108     };
109 };
110 
111 class CallCoStubBuilder : public StubBuilder {
112 public:
CallCoStubBuilder(StubBuilder * parent,EcmaOpcode op)113     explicit CallCoStubBuilder(StubBuilder *parent, EcmaOpcode op)
114         : StubBuilder(parent)
115     {
116         this->op_ = op;
117     }
118     ~CallCoStubBuilder() override = default;
119     NO_MOVE_SEMANTIC(CallCoStubBuilder);
120     NO_COPY_SEMANTIC(CallCoStubBuilder);
GenerateCircuit()121     void GenerateCircuit() override {}
122     void PrepareArgs(std::vector<GateRef> &args, std::vector<GateRef> &argsFastCall);
123     GateRef CallStubDispatch(bool useCmc);
124     std::tuple<bool, size_t, size_t> GetOpInfo();
125     static void LowerFastCall(GateRef gate, GateRef glue, CircuitBuilder &builder, GateRef func, GateRef argc,
126                               const std::vector<GateRef> &args, const std::vector<GateRef> &fastCallArgs,
127                               Variable *result, Label *exit, bool isNew, bool useCmc);
128     static void FastCallSelector(CircuitBuilder &builder, GateRef glue, GateRef func, GateRef argc, Variable *result,
129                                  Label *exit);
130     static void LowerFastSuperCall(GateRef glue, CircuitBuilder &builder, const std::vector<GateRef> &args,
131                                    GateRef elementsPtr, Variable &result, Label &exit);
132 
133     static GateRef LowerCallNGCRuntime(GateRef glue, CircuitBuilder &builder, GateRef gate, int index,
134                                        const std::vector<GateRef> &args, bool useLabel = false);
135     static void CallNGCRuntimeWithCallTimer(GateRef glue, CircuitBuilder &builder, int index, GateRef gate,
136                                             GateRef func, Variable &result, const std::vector<GateRef> &args);
137 
138 private:
139     GateRef glue_ { Circuit::NullGate() };
140     GateRef actualArgc_ { Circuit::NullGate() };
141     GateRef actualArgv_ { Circuit::NullGate() };
142     GateRef func_ { Circuit::NullGate() };
143     GateRef newTarget_ { Circuit::NullGate() };
144     GateRef hirGate_ { Circuit::NullGate() };
145     EcmaOpcode op_;
146     GateRef thisObj_ { Circuit::NullGate() };
147 };
148 
149 enum class FastCallType {
150     FAST_AOT_CALL,
151     FAST_AOT_CALL_BRIDGE,
152     AOT_CALL,
153     AOT_CALL_BRIDGE,
154     SLOW_CALL
155 };
156 
157 class CallStubBuilder : public StubBuilder {
158 public:
159     explicit CallStubBuilder(StubBuilder *parent, GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize,
160                              Variable *result, GateRef hotnessCounter, JSCallArgs callArgs,
161                              ProfileOperation callback = ProfileOperation(),
162                              bool checkIsCallable = true, GateRef hir = Circuit::NullGate())
StubBuilder(parent)163         : StubBuilder(parent)
164     {
165         this->glue_ = glue;
166         this->func_ = func;
167         this->jumpSize_ = jumpSize;
168         this->actualNumArgs_ = actualNumArgs;
169         this->result_ = result;
170         this->hotnessCounter_ = hotnessCounter;
171         this->callArgs_ = callArgs;
172         this->callback_ = callback;
173         this->checkIsCallable_ = checkIsCallable;
174         this->hir_ = hir;
175     }
CallStubBuilder(Environment * env)176     explicit CallStubBuilder(Environment *env)
177         : StubBuilder(env) {}
178     ~CallStubBuilder() override = default;
179     NO_MOVE_SEMANTIC(CallStubBuilder);
180     NO_COPY_SEMANTIC(CallStubBuilder);
GenerateCircuit()181     void GenerateCircuit() override {}
182 
183     void JSCallDispatchForBaseline(Label *exit, Label *noNeedCheckException = nullptr);
184     GateRef JSCallDispatch();
185 
186 protected:
187 
188 private:
189     GateRef glue_ {0};
190     GateRef func_ {0};
191     GateRef jumpSize_ {0};
192     GateRef actualNumArgs_ {0};
193     GateRef hotnessCounter_ {0};
194     Variable *result_ {nullptr};
195     JSCallArgs callArgs_;
196     ProfileOperation callback_;
197     bool checkIsCallable_ {true};
198     GateRef hir_ {0};
199 
200     bool isFast_ {true};
201     bool isBridge_ {false};
202     bool isForBaseline_ {false};
203     GateRef sp_ {0};
204     GateRef method_ {0};
205     GateRef numArgs_ {0};
206     GateRef bitfield_ {0};
207     GateRef callField_ {0};
208     GateRef newTarget_ {0};
209     GateRef thisValue_ {0};
210     GateRef nativeCode_ {0};
211     GateRef realNumArgs_ {0};
212     GateRef isNativeMask_ {0};
213     GateRef baselineBuiltinFp_ {0};
214 
215     void JSCallInit(Label *exit, Label *funcIsHeapObject, Label *funcIsCallable, Label *funcNotCallable);
216     void JSCallNative(Label *exit);
217     void JSCallNativeInner(Label *exit, bool isJSFunction);
218     void JSCallJSFunction(Label *exit, Label *noNeedCheckException = nullptr);
219     void JSFastAotCall(Label *exit);
220     void JSSlowAotCall(Label *exit);
221     GateRef CallConstructorBridge(const int idxForAot, const std::vector<GateRef> &argsForAot);
222     void CallBridge(GateRef code, GateRef expectedNum, Label *exit);
223     void JSCallAsmInterpreter(bool hasBaselineCode, Label *methodNotAot, Label *exit, Label *noNeedCheckException);
224 
225     int PrepareIdxForNative();
226     std::vector<GateRef> PrepareArgsForNative();
227     std::vector<GateRef> PrepareBasicArgsForNative();
228     std::vector<GateRef> PrepareAppendArgsForNative();
229 
230     int PrepareIdxForAot();
231     std::vector<GateRef> PrepareArgsForAot(GateRef expectedNum);
232     std::vector<GateRef> PrepareBasicArgsForAot();
233     std::vector<GateRef> PrepareAppendArgsForAotStep1();
234     std::vector<GateRef> PrepareAppendArgsForAotStep2();
235     std::vector<GateRef> PrepareAppendArgsForAotStep3(GateRef expectedNum);
236 
237     int PrepareIdxForAsmInterpreterForBaselineWithBaselineCode();
238     int PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode();
239     int PrepareIdxForAsmInterpreterWithBaselineCode();
240     int PrepareIdxForAsmInterpreterWithoutBaselineCode();
241     std::vector<GateRef> PrepareArgsForAsmInterpreter();
242     std::vector<GateRef> PrepareBasicArgsForAsmInterpreter();
243     std::vector<GateRef> PrepareAppendArgsForAsmInterpreter();
244 
245     void CallFastBuiltin(Label* notFastBuiltins, Label *exit, GateRef hir = Circuit::NullGate());
246     std::vector<GateRef> PrepareArgsForFastBuiltin();
247     std::vector<GateRef> PrepareBasicArgsForFastBuiltin();
248     std::vector<GateRef> PrepareAppendArgsForFastBuiltin();
249     bool IsCallModeSupportPGO() const;
250     bool IsCallModeSupportCallBuiltin() const;
251     bool IsSlowAotCall() const;
252     bool IsFastAotCall() const;
253     bool IsSlowAotCallWithBridge() const;
254     bool IsFastAotCallWithBridge() const;
255     bool CheckResultValueChangedWithReturn(GateRef prevResRef) const;
256     void HandleProfileCall();
257     void HandleProfileNativeCall();
258     bool IsCallModeGetterSetter();
259 };
260 
261 }   // panda::ecmascript::kungfu
262 #endif  // ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H
263