• 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 
25 enum class FrameTransitionType : uint8_t {
26     BASELINE_TO_OTHER,
27     BASELINE_TO_BASELINE_CHECK,
28     OTHER_TO_BASELINE_CHECK,
29     OTHER_TO_OTHER
30 };
31 
32 class CommonCall {
33 public:
34     static constexpr int FRAME_SLOT_SIZE = 8;
35     static constexpr int DOUBLE_SLOT_SIZE = 16;
36     static constexpr int TRIPLE_SLOT_SIZE = 24;
37     static constexpr int QUADRUPLE_SLOT_SIZE = 32;
38     static constexpr int QUINTUPLE_SLOT_SIZE = 40;
39     static constexpr int SEXTUPLE_SLOT_SIZE = 48;
40     static void CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV);
41     static void PushAsmInterpBridgeFrame(ExtendedAssembler *assembler);
42     static void PopAsmInterpBridgeFrame(ExtendedAssembler *assembler);
43     static void PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc);
44     static void GetArgvAtStack(ExtendedAssembler *assembler);
45     static void PushArgsWithArgvAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc, Register argv,
46         Register op1, Register op2, Label *stackOverflow);
47     static void StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register numArgs, Register op1,
48         Register op2, Label *stackOverflow);
49 };
50 
51 class OptimizedCall : public CommonCall {
52 public:
53     static void CallRuntime(ExtendedAssembler *assembler);
54 
55     static void DeoptPushAsmInterpBridgeFrame(ExtendedAssembler *assembler, Register context);
56 
57     static void JSFunctionEntry(ExtendedAssembler *assembler);
58 
59     static void OptimizedCallAndPushArgv(ExtendedAssembler *assembler);
60 
61     static void JSProxyCallInternalWithArgV(ExtendedAssembler *assembler);
62 
63     static void JSCall(ExtendedAssembler *assembler);
64 
65     static void CallOptimized(ExtendedAssembler *assembler);
66 
67     static void CallRuntimeWithArgv(ExtendedAssembler *assembler);
68 
69     static void JSCallWithArgV(ExtendedAssembler *assembler);
70 
71     static void JSCallWithArgVAndPushArgv(ExtendedAssembler *assembler);
72 
73     static void SuperCallWithArgV(ExtendedAssembler *assembler);
74 
75     static void AOTCallToAsmInterBridge(ExtendedAssembler *assembler);
76 
77     static void FastCallToAsmInterBridge(ExtendedAssembler *assembler);
78 
79     static void DeoptHandlerAsm(ExtendedAssembler *assembler);
80 
81     static void JSCallNew(ExtendedAssembler *assembler);
82 
83     static void GenJSCall(ExtendedAssembler *assembler, bool isNew);
84 
85     static void GenJSCallWithArgV(ExtendedAssembler *assembler, int id);
86 private:
87     static void DeoptEnterAsmInterpOrBaseline(ExtendedAssembler *assembler);
88     static void JSCallCheck(ExtendedAssembler *assembler, Register jsFuncReg,
89                             Label *lNonCallable, Label *lNotJSFunction, Label *lJSFunctionCall);
90     static void ThrowNonCallableInternal(ExtendedAssembler *assembler, Register glueReg);
91     static void JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register jsFuncReg, Label *jsCall);
92     static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler);
93     static void PushArgsWithArgV(ExtendedAssembler *assembler, Register jsfunc,
94                                  Register actualNumArgs, Register argV, Label *pushCallThis);
95     static void PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc,
96                                     Register thisObj, Register newTarget);
97     static void PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs);
98     static void PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp);
99     static void PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue);
100     static void PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp);
101     static void PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler);
102     static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
103     static void CallBuiltinTrampoline(ExtendedAssembler *assembler, Register temp);
104     static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
105     static void CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
106                                            Register glue, Register temp);
107     static void RemoveArgv(ExtendedAssembler *assembler, Register temp);
108 
109     friend class OptimizedFastCall;
110 };
111 
112 class OptimizedFastCall : public CommonCall {
113 public:
114     static void OptimizedFastCallEntry(ExtendedAssembler *assembler);
115 
116     static void OptimizedFastCallAndPushArgv(ExtendedAssembler *assembler);
117 
118     static void JSFastCallWithArgV(ExtendedAssembler *assembler);
119 
120     static void JSFastCallWithArgVAndPushArgv(ExtendedAssembler *assembler);
121 };
122 
123 class AsmInterpreterCall : public CommonCall {
124 public:
125     static void GeneratorReEnterAsmInterp(ExtendedAssembler *assembler);
126 
127     static void GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler);
128 
129     static void AsmInterpEntryDispatch(ExtendedAssembler *assembler);
130 
131     static void AsmInterpreterEntry(ExtendedAssembler *assembler);
132 
133     static void PushCallThisRangeAndDispatch(ExtendedAssembler *assembler);
134 
135     static void PushCallRangeAndDispatch(ExtendedAssembler *assembler);
136 
137     static void PushCallArgs3AndDispatch(ExtendedAssembler *assembler);
138 
139     static void PushCallArgs2AndDispatch(ExtendedAssembler *assembler);
140 
141     static void PushCallArg1AndDispatch(ExtendedAssembler *assembler);
142 
143     static void PushCallArg0AndDispatch(ExtendedAssembler *assembler);
144 
145     static void PushCallThisArg0AndDispatch(ExtendedAssembler *assembler);
146 
147     static void PushCallThisArg1AndDispatch(ExtendedAssembler *assembler);
148 
149     static void PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler);
150 
151     static void PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler);
152 
153     static void PushCallNewAndDispatch(ExtendedAssembler *assembler);
154 
155     static void PushSuperCallAndDispatch(ExtendedAssembler *assembler);
156 
157     static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler);
158 
159     static void PushNewTargetAndDispatchNative(ExtendedAssembler *assembler);
160 
161     static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler);
162 
163     static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler);
164 
165     static void ResumeRspAndDispatch(ExtendedAssembler *assembler);
166 
167     static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler);
168 
169     static void ResumeRspAndReturnBaseline([[maybe_unused]] ExtendedAssembler *assembler);
170 
171     static void CallGetter(ExtendedAssembler *assembler);
172 
173     static void CallSetter(ExtendedAssembler *assembler);
174 
175     static void CallContainersArgs2(ExtendedAssembler *assembler);
176 
177     static void CallContainersArgs3(ExtendedAssembler *assembler);
178 
179     static void CallReturnWithArgv(ExtendedAssembler *assembler);
180 
181     static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler);
182 
183     static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
184 
185     static void ResumeRspAndRollback(ExtendedAssembler *assembler);
186 
187     static void ASMFastWriteBarrier(ExtendedAssembler *assembler);
188 private:
189     static void PushFrameState(ExtendedAssembler *assembler, Register prevSpRegister, Register fpRegister,
190         Register callTargetRegister, Register thisRegister, Register methodRegister, Register pcRegister,
191         Register operatorRegister);
192     static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register prevSpRegister,
193         Register fpRegister, Register callTargetRegister, Register thisRegister, Register methodRegister,
194         Register contextRegister, Register pcRegister, Register operatorRegister);
195     static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler);
196     static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler);
197     static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
198         Register declaredNumArgsRegister);
199     static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
200         Register numVregsRegister);
201     static void PushUndefinedWithArgcAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc,
202         Register op1, Register op2, Label *stackOverflow);
203     static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp,
204         Register op);
205     static void ThrowStackOverflowExceptionAndReturnToAsmInterpBridgeFrame(ExtendedAssembler *assembler, Register glue,
206         Register fp, Register op);
207     static void HasPendingException(ExtendedAssembler *assembler, Register threadRegister);
208     static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode,
209                              Label *stackOverflow, FrameTransitionType type);
210     static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
211     static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
212     static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow, FrameTransitionType type);
213     static void DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister,
214                              Register callTargetRegister, Register methodRegister, Register accRegister = rInvalid,
215                              bool hasException = false);
216     static void CallNativeEntry(ExtendedAssembler *assembler, bool isJSFunction);
217     static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
218     static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
219     static bool PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type);
220     static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, FrameTransitionType type);
221     static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);
222     static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
223         Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
224     static void PreserveMostCall(ExtendedAssembler* assembler);
225     static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label &needcall);
226     friend class OptimizedCall;
227     friend class BaselineCall;
228 };
229 
230 class BaselineCall : public CommonCall {
231 public:
232     /* other call baseline: need to check whether baseline code exists */
233     static void CallArg0AndCheckToBaseline(ExtendedAssembler *assembler);
234     static void CallArg1AndCheckToBaseline(ExtendedAssembler *assembler);
235     static void CallArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
236     static void CallArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
237     static void CallThisArg0AndCheckToBaseline(ExtendedAssembler *assembler);
238     static void CallThisArg1AndCheckToBaseline(ExtendedAssembler *assembler);
239     static void CallThisArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
240     static void CallThisArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
241     static void CallRangeAndCheckToBaseline(ExtendedAssembler *assembler);
242     static void CallNewAndCheckToBaseline(ExtendedAssembler *assembler);
243     static void SuperCallAndCheckToBaseline(ExtendedAssembler *assembler);
244     static void CallThisRangeAndCheckToBaseline(ExtendedAssembler *assembler);
245     /* baseline call other: need to save fp and lr */
246     static void CallArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
247     static void CallArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
248     static void CallArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
249     static void CallArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
250     static void CallThisArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
251     static void CallThisArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
252     static void CallThisArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
253     static void CallThisArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
254     static void CallRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
255     static void CallNewAndDispatchFromBaseline(ExtendedAssembler *assembler);
256     static void SuperCallAndDispatchFromBaseline(ExtendedAssembler *assembler);
257     static void CallThisRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
258     /* baseline call baseline: need to check whether baseline code exists and save fp and lr */
259     static void CallArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
260     static void CallArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
261     static void CallArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
262     static void CallArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
263     static void CallThisArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
264     static void CallThisArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
265     static void CallThisArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
266     static void CallThisArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
267     static void CallRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
268     static void CallNewAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
269     static void SuperCallAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
270     static void CallThisRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
271     /* get baselineBuiltinFp when baselineBuiltin call the others */
272     static void GetBaselineBuiltinFp(ExtendedAssembler *assembler);
273 };
274 
275 class JsFunctionArgsConfigFrameScope {
276 public:
277     static constexpr int FRAME_SLOT_SIZE = 8;
JsFunctionArgsConfigFrameScope(ExtendedAssembler * assembler)278     explicit JsFunctionArgsConfigFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
279     {
280         assembler_->Pushq(rbp);
281         assembler_->Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME));
282         // 2: skip jsFunc and frameType
283         assembler_->Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
284         // callee save
285         assembler_->Pushq(r12);
286         assembler_->Pushq(r13);
287         assembler_->Pushq(r14);
288         assembler_->Pushq(rbx);
289         assembler_->Pushq(rax);
290     }
~JsFunctionArgsConfigFrameScope()291     ~JsFunctionArgsConfigFrameScope()
292     {
293         assembler_->Movq(rbp, rsp);
294         assembler_->Addq(-5 * FRAME_SLOT_SIZE, rsp); // -5: get r12 r13 r14 rbx
295         assembler_->Popq(rbx);
296         assembler_->Popq(r14);
297         assembler_->Popq(r13);
298         assembler_->Popq(r12);
299         assembler_->Addq(FRAME_SLOT_SIZE, rsp); // skip frame type
300         assembler_->Pop(rbp);
301         assembler_->Ret();
302     }
303     NO_COPY_SEMANTIC(JsFunctionArgsConfigFrameScope);
304     NO_MOVE_SEMANTIC(JsFunctionArgsConfigFrameScope);
305 private:
306     ExtendedAssembler *assembler_;
307 };
308 
309 class OptimizedUnfoldArgVFrameFrameScope {
310 public:
311     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler * assembler)312     explicit OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
313     {
314         assembler_->Pushq(rbp);
315         // construct frame
316         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
317         assembler_->Pushq(assembler_->AvailableRegister2());
318         // 2: skip callSiteSp and frameType
319         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
320         assembler_->Pushq(rbx);
321         assembler_->Pushq(r12); // callee save
322     }
~OptimizedUnfoldArgVFrameFrameScope()323     ~OptimizedUnfoldArgVFrameFrameScope()
324     {
325         assembler_->Movq(rbp, rsp);
326         assembler_->Addq(-4 * FRAME_SLOT_SIZE, rsp); // -4: get r12 rbx
327         assembler_->Popq(r12);
328         assembler_->Popq(rbx);
329         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
330         assembler_->Popq(rbp);
331         assembler_->Ret();
332     }
333     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
334     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
335 private:
336     ExtendedAssembler *assembler_;
337 };
338 
339 class OptimizedUnfoldArgVFrameFrame1Scope {
340 public:
341     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler * assembler)342     explicit OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler *assembler) : assembler_(assembler)
343     {
344         assembler_->Pushq(rbp);
345         // construct frame
346         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
347         assembler_->Pushq(assembler_->AvailableRegister2());
348         // 2: skip callSiteSp and frameType
349         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
350         assembler_->Pushq(rbx);
351         assembler_->Pushq(r12); // callee save
352         assembler_->Pushq(r13);
353         assembler_->Pushq(r14); // callee save
354     }
~OptimizedUnfoldArgVFrameFrame1Scope()355     ~OptimizedUnfoldArgVFrameFrame1Scope()
356     {
357         assembler_->Movq(rbp, rsp);
358         assembler_->Addq(-6 * FRAME_SLOT_SIZE, rsp); // -6: get r12 r13 r14 rbx
359         assembler_->Popq(r14);
360         assembler_->Popq(r13);
361         assembler_->Popq(r12);
362         assembler_->Popq(rbx);
363         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
364         assembler_->Popq(rbp);
365         assembler_->Ret();
366     }
367     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
368     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
369 private:
370     ExtendedAssembler *assembler_;
371 };
372 }  // namespace panda::ecmascript::x64
373 #endif  // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
374