• 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 PushSuperCallAndDispatch(ExtendedAssembler *assembler);
137 
138     static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler);
139 
140     static void PushNewTargetAndDispatchNative(ExtendedAssembler *assembler);
141 
142     static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler);
143 
144     static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler);
145 
146     static void ResumeRspAndDispatch(ExtendedAssembler *assembler);
147 
148     static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler);
149 
150     static void CallGetter(ExtendedAssembler *assembler);
151 
152     static void CallSetter(ExtendedAssembler *assembler);
153 
154     static void CallContainersArgs3(ExtendedAssembler *assembler);
155 
156     static void CallReturnWithArgv(ExtendedAssembler *assembler);
157 
158     static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler);
159 
160     static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
161 
162     static void ResumeRspAndRollback(ExtendedAssembler *assembler);
163 
164 private:
165     static void PushFrameState(ExtendedAssembler *assembler, Register prevSpRegister, Register fpRegister,
166         Register callTargetRegister, Register thisRegister, Register methodRegister, Register pcRegister,
167         Register operatorRegister);
168     static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register prevSpRegister,
169         Register fpRegister, Register callTargetRegister, Register thisRegister, Register methodRegister,
170         Register contextRegister, Register pcRegister, Register operatorRegister);
171     static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler);
172     static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler);
173     static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
174         Register declaredNumArgsRegister);
175     static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
176         Register numVregsRegister);
177     static void PushUndefinedWithArgcAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc,
178         Register op1, Register op2, Label *stackOverflow);
179     static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp,
180         Register op);
181     static void HasPendingException(ExtendedAssembler *assembler, Register threadRegister);
182     static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);
183     static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
184     static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
185     static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow);
186     static void DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister,
187                              Register methodRegister, Register accRegister = rInvalid);
188     static void CallNativeEntry(ExtendedAssembler *assemblSer);
189     static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
190     static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
191     static void PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type);
192     static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode);
193     static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);
194     static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
195         Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
196     friend class OptimizedCall;
197 };
198 
199 class JsFunctionArgsConfigFrameScope {
200 public:
201     static constexpr int FRAME_SLOT_SIZE = 8;
JsFunctionArgsConfigFrameScope(ExtendedAssembler * assembler)202     explicit JsFunctionArgsConfigFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
203     {
204         assembler_->Pushq(rbp);
205         assembler_->Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME));
206         // 2: skip jsFunc and frameType
207         assembler_->Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
208         // callee save
209         assembler_->Pushq(r12);
210         assembler_->Pushq(r13);
211         assembler_->Pushq(r14);
212         assembler_->Pushq(rbx);
213         assembler_->Pushq(rax);
214     }
~JsFunctionArgsConfigFrameScope()215     ~JsFunctionArgsConfigFrameScope()
216     {
217         assembler_->Movq(rbp, rsp);
218         assembler_->Addq(-5 * FRAME_SLOT_SIZE, rsp); // -5: get r12 r13 r14 rbx
219         assembler_->Popq(rbx);
220         assembler_->Popq(r14);
221         assembler_->Popq(r13);
222         assembler_->Popq(r12);
223         assembler_->Addq(FRAME_SLOT_SIZE, rsp); // skip frame type
224         assembler_->Pop(rbp);
225         assembler_->Ret();
226     }
227     NO_COPY_SEMANTIC(JsFunctionArgsConfigFrameScope);
228     NO_MOVE_SEMANTIC(JsFunctionArgsConfigFrameScope);
229 private:
230     ExtendedAssembler *assembler_;
231 };
232 
233 class OptimizedUnfoldArgVFrameFrameScope {
234 public:
235     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler * assembler)236     explicit OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
237     {
238         assembler_->Pushq(rbp);
239         // construct frame
240         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
241         assembler_->Pushq(assembler_->AvailableRegister2());
242         // 2: skip callSiteSp and frameType
243         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
244         assembler_->Pushq(rbx);
245         assembler_->Pushq(r12); // callee save
246     }
~OptimizedUnfoldArgVFrameFrameScope()247     ~OptimizedUnfoldArgVFrameFrameScope()
248     {
249         assembler_->Movq(rbp, rsp);
250         assembler_->Addq(-4 * FRAME_SLOT_SIZE, rsp); // -4: get r12 rbx
251         assembler_->Popq(r12);
252         assembler_->Popq(rbx);
253         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
254         assembler_->Popq(rbp);
255         assembler_->Ret();
256     }
257     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
258     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
259 private:
260     ExtendedAssembler *assembler_;
261 };
262 
263 class OptimizedUnfoldArgVFrameFrame1Scope {
264 public:
265     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler * assembler)266     explicit OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler *assembler) : assembler_(assembler)
267     {
268         assembler_->Pushq(rbp);
269         // construct frame
270         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
271         assembler_->Pushq(assembler_->AvailableRegister2());
272         // 2: skip callSiteSp and frameType
273         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
274         assembler_->Pushq(rbx);
275         assembler_->Pushq(r12); // callee save
276         assembler_->Pushq(r13);
277         assembler_->Pushq(r14); // callee save
278     }
~OptimizedUnfoldArgVFrameFrame1Scope()279     ~OptimizedUnfoldArgVFrameFrame1Scope()
280     {
281         assembler_->Movq(rbp, rsp);
282         assembler_->Addq(-6 * FRAME_SLOT_SIZE, rsp); // -6: get r12 r13 r14 rbx
283         assembler_->Popq(r14);
284         assembler_->Popq(r13);
285         assembler_->Popq(r12);
286         assembler_->Popq(rbx);
287         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
288         assembler_->Popq(rbp);
289         assembler_->Ret();
290     }
291     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
292     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
293 private:
294     ExtendedAssembler *assembler_;
295 };
296 }  // namespace panda::ecmascript::x64
297 #endif  // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
298