• 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();
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);
128 
129  private:
130     GateRef glue_ { Circuit::NullGate() };
131     GateRef actualArgc_ { Circuit::NullGate() };
132     GateRef actualArgv_ { Circuit::NullGate() };
133     GateRef func_ { Circuit::NullGate() };
134     GateRef newTarget_ { Circuit::NullGate() };
135     GateRef hirGate_ { Circuit::NullGate() };
136     EcmaOpcode op_;
137     GateRef thisObj_ { Circuit::NullGate() };
138 };
139 
140 
141 class CallStubBuilder : public StubBuilder {
142 public:
143     explicit CallStubBuilder(StubBuilder *parent, GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize,
144                              Variable *result, GateRef hotnessCounter, JSCallArgs callArgs,
145                              ProfileOperation callback = ProfileOperation(),
146                              bool checkIsCallable = true, GateRef hir = Circuit::NullGate())
StubBuilder(parent)147         : StubBuilder(parent)
148     {
149         this->glue_ = glue;
150         this->func_ = func;
151         this->jumpSize_ = jumpSize;
152         this->actualNumArgs_ = actualNumArgs;
153         this->result_ = result;
154         this->hotnessCounter_ = hotnessCounter;
155         this->callArgs_ = callArgs;
156         this->callback_ = callback;
157         this->checkIsCallable_ = checkIsCallable;
158         this->hir_ = hir;
159     }
CallStubBuilder(Environment * env)160     explicit CallStubBuilder(Environment *env)
161         : StubBuilder(env) {}
162     ~CallStubBuilder() override = default;
163     NO_MOVE_SEMANTIC(CallStubBuilder);
164     NO_COPY_SEMANTIC(CallStubBuilder);
GenerateCircuit()165     void GenerateCircuit() override {}
166 
167     void JSCallDispatchForBaseline(Label *exit, Label *noNeedCheckException = nullptr);
168     GateRef JSCallDispatch();
169 
170 protected:
171 
172 private:
173     GateRef glue_ {0};
174     GateRef func_ {0};
175     GateRef jumpSize_ {0};
176     GateRef actualNumArgs_ {0};
177     GateRef hotnessCounter_ {0};
178     Variable *result_ {nullptr};
179     JSCallArgs callArgs_;
180     ProfileOperation callback_;
181     bool checkIsCallable_ {true};
182     GateRef hir_ {0};
183 
184     bool isFast_ {true};
185     bool isBridge_ {false};
186     bool isForBaseline_ {false};
187     GateRef sp_ {0};
188     GateRef method_ {0};
189     GateRef numArgs_ {0};
190     GateRef bitfield_ {0};
191     GateRef callField_ {0};
192     GateRef newTarget_ {0};
193     GateRef thisValue_ {0};
194     GateRef nativeCode_ {0};
195     GateRef realNumArgs_ {0};
196     GateRef isNativeMask_ {0};
197     GateRef baselineBuiltinFp_ {0};
198 
199     void JSCallInit(Label *exit, Label *funcIsHeapObject, Label *funcIsCallable, Label *funcNotCallable);
200     void JSCallNative(Label *exit);
201     void JSCallNativeInner(Label *exit, bool isJsProxy);
202     void JSCallJSFunction(Label *exit, Label *noNeedCheckException = nullptr);
203     void JSFastAotCall(Label *exit);
204     void JSSlowAotCall(Label *exit);
205     GateRef CallConstructorBridge(const int idxForAot, const std::vector<GateRef> &argsForAot);
206     void CallBridge(GateRef code, GateRef expectedNum, Label *exit);
207     void JSCallAsmInterpreter(bool hasBaselineCode, Label *exit, Label *noNeedCheckException);
208 
209     int PrepareIdxForNative();
210     std::vector<GateRef> PrepareArgsForNative();
211     std::vector<GateRef> PrepareBasicArgsForNative();
212     std::vector<GateRef> PrepareAppendArgsForNative();
213 
214     int PrepareIdxForAot();
215     std::vector<GateRef> PrepareArgsForAot(GateRef expectedNum);
216     std::vector<GateRef> PrepareBasicArgsForAot();
217     std::vector<GateRef> PrepareAppendArgsForAotStep1();
218     std::vector<GateRef> PrepareAppendArgsForAotStep2();
219     std::vector<GateRef> PrepareAppendArgsForAotStep3(GateRef expectedNum);
220 
221     int PrepareIdxForAsmInterpreterForBaselineWithBaselineCode();
222     int PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode();
223     int PrepareIdxForAsmInterpreterWithBaselineCode();
224     int PrepareIdxForAsmInterpreterWithoutBaselineCode();
225     std::vector<GateRef> PrepareArgsForAsmInterpreter();
226     std::vector<GateRef> PrepareBasicArgsForAsmInterpreter();
227     std::vector<GateRef> PrepareAppendArgsForAsmInterpreter();
228 
229     void CallFastBuiltin(Label* notFastBuiltins, Label *exit, GateRef hir = Circuit::NullGate());
230     std::vector<GateRef> PrepareArgsForFastBuiltin();
231     std::vector<GateRef> PrepareBasicArgsForFastBuiltin();
232     std::vector<GateRef> PrepareAppendArgsForFastBuiltin();
233     bool IsCallModeSupportPGO() const;
234     bool IsCallModeSupportCallBuiltin() const;
235     bool IsSlowAotCall() const;
236     bool IsFastAotCall() const;
237     bool IsSlowAotCallWithBridge() const;
238     bool IsFastAotCallWithBridge() const;
239     bool CheckResultValueChangedWithReturn(GateRef prevResRef) const;
240     void HandleProfileCall();
241     void HandleProfileNativeCall();
242     bool IsCallModeGetterSetter();
243 };
244 
245 }   // panda::ecmascript::kungfu
246 #endif  // ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H
247