• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_ASSEMBLER_MODULE_X64_H
17 #define ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
18 
19 #include "ecmascript/compiler/assembler/x64/assembler_x64.h"
20 #include "ecmascript/compiler/assembler/x64/extended_assembler_x64.h"
21 #include "ecmascript/frames.h"
22 
23 namespace panda::ecmascript::x64 {
24 class CommonCall {
25 public:
26     static constexpr int FRAME_SLOT_SIZE = 8;
27     static constexpr int DOUBLE_SLOT_SIZE = 16;
28     static constexpr int TRIPLE_SLOT_SIZE = 24;
29     static constexpr int QUADRUPLE_SLOT_SIZE = 32;
30     static constexpr int QUINTUPLE_SLOT_SIZE = 40;
31     static constexpr int SEXTUPLE_SLOT_SIZE = 48;
32     static void CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV);
33     static void PushAsmInterpBridgeFrame(ExtendedAssembler *assembler);
34     static void PopAsmInterpBridgeFrame(ExtendedAssembler *assembler);
35     static void PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc);
36     static void GetArgvAtStack(ExtendedAssembler *assembler);
37     static void PushArgsWithArgvAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc, Register argv,
38         Register op1, Register op2, Label *stackOverflow);
39     static void StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register numArgs, Register op1,
40         Register op2, Label *stackOverflow);
41 };
42 
43 class OptimizedCall : public CommonCall {
44 public:
45     static void CallRuntime(ExtendedAssembler *assembler);
46 
47     static void JSFunctionEntry(ExtendedAssembler *assembler);
48 
49     static void OptimizedCallAndPushUndefined(ExtendedAssembler *assembler);
50 
51     static void CallBuiltinTrampoline(ExtendedAssembler *assembler);
52 
53     static void JSProxyCallInternalWithArgV(ExtendedAssembler *assembler);
54 
55     static void JSCall(ExtendedAssembler *assembler);
56 
57     static void CallOptimized(ExtendedAssembler *assembler);
58 
59     static void CallRuntimeWithArgv(ExtendedAssembler *assembler);
60 
61     static void JSCallWithArgV(ExtendedAssembler *assembler);
62 
63     static void JSCallWithArgVAndPushUndefined(ExtendedAssembler *assembler);
64 
65     static void DeoptHandlerAsm(ExtendedAssembler *assembler);
66 
67     static void JSCallNew(ExtendedAssembler *assembler);
68 
69     static void GenJSCall(ExtendedAssembler *assembler, bool isNew);
70 
71     static void GenJSCallWithArgV(ExtendedAssembler *assembler, bool needAddExpectedArgs);
72 private:
73     static void DeoptEnterAsmInterp(ExtendedAssembler *assembler);
74     static void JSCallCheck(ExtendedAssembler *assembler, Register jsFuncReg,
75                             Label *lNonCallable, Label *lNotJSFunction, Label *lJSFunctionCall);
76     static void ThrowNonCallableInternal(ExtendedAssembler *assembler, Register glueReg);
77     static void JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register jsFuncReg, Label *jsCall);
78     static void JSProxyCallInternal(ExtendedAssembler *assembler, Register jsFuncReg);
79     static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler);
80     static void PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
81                                  Register actualNumArgs, Register argV, Label *pushCallThis);
82     static void PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc,
83                                     Register thisObj, Register newTarget);
84     static void PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs);
85     static void PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp);
86     static void PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue);
87     static void PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp);
88     static void PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler);
89 
90     friend class OptimizedFastCall;
91 };
92 
93 class OptimizedFastCall : public CommonCall {
94 public:
95     static void OptimizedFastCallEntry(ExtendedAssembler *assembler);
96 
97     static void OptimizedFastCallAndPushUndefined(ExtendedAssembler *assembler);
98 
99     static void JSFastCallWithArgV(ExtendedAssembler *assembler);
100 
101     static void JSFastCallWithArgVAndPushUndefined(ExtendedAssembler *assembler);
102 };
103 
104 class AsmInterpreterCall : public CommonCall {
105 public:
106     static void GeneratorReEnterAsmInterp(ExtendedAssembler *assembler);
107 
108     static void GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler);
109 
110     static void AsmInterpEntryDispatch(ExtendedAssembler *assembler);
111 
112     static void AsmInterpreterEntry(ExtendedAssembler *assembler);
113 
114     static void PushCallThisRangeAndDispatch(ExtendedAssembler *assembler);
115 
116     static void PushCallRangeAndDispatch(ExtendedAssembler *assembler);
117 
118     static void PushCallArgs3AndDispatch(ExtendedAssembler *assembler);
119 
120     static void PushCallArgs2AndDispatch(ExtendedAssembler *assembler);
121 
122     static void PushCallArg1AndDispatch(ExtendedAssembler *assembler);
123 
124     static void PushCallArg0AndDispatch(ExtendedAssembler *assembler);
125 
126     static void PushCallThisArg0AndDispatch(ExtendedAssembler *assembler);
127 
128     static void PushCallThisArg1AndDispatch(ExtendedAssembler *assembler);
129 
130     static void PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler);
131 
132     static void PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler);
133 
134     static void PushCallNewAndDispatch(ExtendedAssembler *assembler);
135 
136     static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler);
137 
138     static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler);
139 
140     static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler);
141 
142     static void ResumeRspAndDispatch(ExtendedAssembler *assembler);
143 
144     static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler);
145 
146     static void CallGetter(ExtendedAssembler *assembler);
147 
148     static void CallSetter(ExtendedAssembler *assembler);
149 
150     static void CallContainersArgs3(ExtendedAssembler *assembler);
151 
152     static void CallReturnWithArgv(ExtendedAssembler *assembler);
153 
154     static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler);
155 
156     static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
157 
158 private:
159     static void PushFrameState(ExtendedAssembler *assembler, Register prevSpRegister, Register fpRegister,
160         Register callTargetRegister, Register thisRegister, Register methodRegister, Register pcRegister,
161         Register operatorRegister);
162     static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register prevSpRegister,
163         Register fpRegister, Register callTargetRegister, Register thisRegister, Register methodRegister,
164         Register contextRegister, Register pcRegister, Register operatorRegister);
165     static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler);
166     static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler);
167     static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
168         Register declaredNumArgsRegister);
169     static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
170         Register numVregsRegister);
171     static void PushUndefinedWithArgcAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc,
172         Register op1, Register op2, Label *stackOverflow);
173     static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp,
174         Register op);
175     static void HasPendingException(ExtendedAssembler *assembler, Register threadRegister);
176     static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);
177     static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
178     static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
179     static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow);
180     static void DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister,
181                              Register methodRegister, Register accRegister = rInvalid);
182     static void CallNativeEntry(ExtendedAssembler *assemblSer);
183     static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew);
184     static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
185     static void PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type);
186     static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode);
187     static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);
188     static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
189         Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
190     friend class OptimizedCall;
191 };
192 
193 class JsFunctionArgsConfigFrameScope {
194 public:
195     static constexpr int FRAME_SLOT_SIZE = 8;
JsFunctionArgsConfigFrameScope(ExtendedAssembler * assembler)196     explicit JsFunctionArgsConfigFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
197     {
198         assembler_->Pushq(rbp);
199         assembler_->Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME));
200         // 2: skip jsFunc and frameType
201         assembler_->Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
202         // callee save
203         assembler_->Pushq(r12);
204         assembler_->Pushq(r13);
205         assembler_->Pushq(r14);
206         assembler_->Pushq(rbx);
207         assembler_->Pushq(rax);
208     }
~JsFunctionArgsConfigFrameScope()209     ~JsFunctionArgsConfigFrameScope()
210     {
211         assembler_->Movq(rbp, rsp);
212         assembler_->Addq(-5 * FRAME_SLOT_SIZE, rsp); // -5: get r12 r13 r14 rbx
213         assembler_->Popq(rbx);
214         assembler_->Popq(r14);
215         assembler_->Popq(r13);
216         assembler_->Popq(r12);
217         assembler_->Addq(FRAME_SLOT_SIZE, rsp); // skip frame type
218         assembler_->Pop(rbp);
219         assembler_->Ret();
220     }
221     NO_COPY_SEMANTIC(JsFunctionArgsConfigFrameScope);
222     NO_MOVE_SEMANTIC(JsFunctionArgsConfigFrameScope);
223 private:
224     ExtendedAssembler *assembler_;
225 };
226 
227 class OptimizedUnfoldArgVFrameFrameScope {
228 public:
229     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler * assembler)230     explicit OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
231     {
232         assembler_->Pushq(rbp);
233         // construct frame
234         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
235         assembler_->Pushq(assembler_->AvailableRegister2());
236         // 2: skip callSiteSp and frameType
237         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
238         assembler_->Pushq(rbx);
239         assembler_->Pushq(r12); // callee save
240     }
~OptimizedUnfoldArgVFrameFrameScope()241     ~OptimizedUnfoldArgVFrameFrameScope()
242     {
243         assembler_->Movq(rbp, rsp);
244         assembler_->Addq(-4 * FRAME_SLOT_SIZE, rsp); // -4: get r12 rbx
245         assembler_->Popq(r12);
246         assembler_->Popq(rbx);
247         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
248         assembler_->Popq(rbp);
249         assembler_->Ret();
250     }
251     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
252     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
253 private:
254     ExtendedAssembler *assembler_;
255 };
256 
257 class OptimizedUnfoldArgVFrameFrame1Scope {
258 public:
259     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler * assembler)260     explicit OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler *assembler) : assembler_(assembler)
261     {
262         assembler_->Pushq(rbp);
263         // construct frame
264         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
265         assembler_->Pushq(assembler_->AvailableRegister2());
266         // 2: skip callSiteSp and frameType
267         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
268         assembler_->Pushq(rbx);
269         assembler_->Pushq(r12); // callee save
270         assembler_->Pushq(r13);
271         assembler_->Pushq(r14); // callee save
272     }
~OptimizedUnfoldArgVFrameFrame1Scope()273     ~OptimizedUnfoldArgVFrameFrame1Scope()
274     {
275         assembler_->Movq(rbp, rsp);
276         assembler_->Addq(-6 * FRAME_SLOT_SIZE, rsp); // -6: get r12 r13 r14 rbx
277         assembler_->Popq(r14);
278         assembler_->Popq(r13);
279         assembler_->Popq(r12);
280         assembler_->Popq(rbx);
281         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
282         assembler_->Popq(rbp);
283         assembler_->Ret();
284     }
285     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
286     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
287 private:
288     ExtendedAssembler *assembler_;
289 };
290 }  // namespace panda::ecmascript::x64
291 #endif  // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
292