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_AARCH64_EXTENDED_ASSEMBLER_H
17#define ECMASCRIPT_COMPILER_AARCH64_EXTENDED_ASSEMBLER_H
18
19#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64.h"
20#include "ecmascript/compiler/assembler/aarch64/extend_assembler.h"
21#include "ecmascript/frames.h"
22
23namespace panda::ecmascript::aarch64 {
24
25enum class FrameTransitionType : uint8_t {
26    BASELINE_TO_OTHER,
27    BASELINE_TO_BASELINE_CHECK,
28    OTHER_TO_BASELINE_CHECK,
29    OTHER_TO_OTHER
30};
31
32using Label = panda::ecmascript::Label;
33class CommonCall {
34public:
35    static constexpr int FRAME_SLOT_SIZE = 8;
36    static constexpr int DOUBLE_SLOT_SIZE = 16;
37    static constexpr int TRIPLE_SLOT_SIZE = 24;
38    static constexpr int QUADRUPLE_SLOT_SIZE = 32;
39    static constexpr int QUINTUPLE_SLOT_SIZE = 40;
40    static constexpr int OCTUPLE_SLOT_SIZE = 64;
41    static constexpr int NONUPLE_SLOT_SIZE = 72;
42    static constexpr int FRAME_SLOT_SIZE_LOG2 = 3;
43    enum BuiltinsLeaveFrameArgId : unsigned {CODE_ADDRESS = 0, ENV, ARGC, ARGV};
44    static inline int64_t GetStackArgOffSetToFp(unsigned argId)
45    {
46        //   +--------------------------+
47        //   |       argv0              | calltarget , newtARGET, this, ....
48        //   +--------------------------+ ---
49        //   |       argc               |   ^
50        //   |--------------------------|   arguments
51        //   |       env                |   |
52        //   |--------------------------|   |
53        //   |       codeAddress        |   |
54        //   |--------------------------|   |
55        //   |       returnAddr         |   |
56        //   |--------------------------| Fixed OptimizedBuiltinLeaveFrame
57        //   |       callsiteFp         |   |
58        //   |--------------------------|   |
59        //   |       frameType          |   v
60        //   +--------------------------+ ---
61        // 16 : 16 means arguments offset to fp
62        return 16 + static_cast<int64_t>(argId) * static_cast<int64_t>(FRAME_SLOT_SIZE);
63    }
64    static void PushUndefinedWithArgc(ExtendedAssembler *assembler, Register glue, Register argc, Register temp,
65        Register fp, Label *next, Label *stackOverflow);
66    static void PushArgsWithArgv(ExtendedAssembler *assembler, Register glue, Register argc, Register argv,
67        Register op, Register fp, Label *next, Label *stackOverflow);
68    static void PushArgsWithArgvInPair(ExtendedAssembler *assembler, Register argc, Register argv, Register padding,
69        Register op1, Register op2, Label *next);
70    static void PushAsmInterpBridgeFrame(ExtendedAssembler *assembler);
71    static void PopAsmInterpBridgeFrame(ExtendedAssembler *assembler);
72    static void StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register currentSlot, Register numArgs,
73        Register op, Label *stackOverflow);
74    static void PushLeaveFrame(ExtendedAssembler *assembler, Register glue);
75    static void PopLeaveFrame(ExtendedAssembler *assembler);
76    static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
77    static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
78};
79
80class OptimizedCall : public CommonCall {
81public:
82    static void CallRuntime(ExtendedAssembler *assembler);
83
84    static void JSFunctionEntry(ExtendedAssembler *assembler);
85
86    static void OptimizedCallAndPushArgv(ExtendedAssembler *assembler);
87
88    static void JSProxyCallInternalWithArgV(ExtendedAssembler *assembler);
89
90    static void JSCall(ExtendedAssembler *assembler);
91
92    static void CallOptimized(ExtendedAssembler *assembler);
93
94    static void CallRuntimeWithArgv(ExtendedAssembler *assembler);
95
96    static void JSCallWithArgV(ExtendedAssembler *assembler);
97
98    static void JSCallWithArgVAndPushArgv(ExtendedAssembler *assembler);
99
100    static void SuperCallWithArgV(ExtendedAssembler *assembler);
101
102    static void AOTCallToAsmInterBridge(ExtendedAssembler *assembler);
103
104    static void FastCallToAsmInterBridge(ExtendedAssembler *assembler);
105
106    static void DeoptHandlerAsm(ExtendedAssembler *assembler);
107
108    static void JSCallNew(ExtendedAssembler *assembler);
109
110    static void GenJSCall(ExtendedAssembler *assembler, bool isNew);
111
112    static void GenJSCallWithArgV(ExtendedAssembler *assembler, int id);
113private:
114    static void DeoptEnterAsmInterp(ExtendedAssembler *assembler);
115    static void JSCallCheck(ExtendedAssembler *assembler, Register jsfunc, Register taggedValue,
116                            Label *nonCallable, Label *notJSFunction);
117    static void ThrowNonCallableInternal(ExtendedAssembler *assembler, Register sp);
118    static void JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register glue,
119                                            Register actualArgC, Register jsfunc, int stubId);
120    static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler);
121    static void PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc,
122                                    Register thisObj, Register newTarget, Register currentSp);
123    static void PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs);
124    static void PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp);
125    static void PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue);
126    static void PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp);
127    static void PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler);
128    static void IncreaseStackForArguments(ExtendedAssembler *assembler, Register argC, Register fp,
129                                          int64_t numExtraArgs = 0);
130    static void PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler);
131    static void PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler);
132    static void JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew = false);
133    static void CallBuiltinTrampoline(ExtendedAssembler *assembler);
134    static void CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
135                                           Register glue, Register temp);
136    friend class OptimizedFastCall;
137};
138
139class OptimizedFastCall : public CommonCall {
140public:
141    static void OptimizedFastCallEntry(ExtendedAssembler *assembler);
142
143    static void OptimizedFastCallAndPushArgv(ExtendedAssembler *assembler);
144
145    static void JSFastCallWithArgV(ExtendedAssembler *assembler);
146
147    static void JSFastCallWithArgVAndPushArgv(ExtendedAssembler *assembler);
148};
149
150class AsmInterpreterCall : public CommonCall {
151public:
152    static void AsmInterpreterEntry(ExtendedAssembler *assembler);
153
154    static void AsmInterpEntryDispatch(ExtendedAssembler *assembler);
155
156    static void GeneratorReEnterAsmInterp(ExtendedAssembler *assembler);
157
158    static void GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler);
159
160    static void PushCallThisRangeAndDispatch(ExtendedAssembler *assembler);
161
162    static void PushCallRangeAndDispatch(ExtendedAssembler *assembler);
163
164    static void PushCallArgs3AndDispatch(ExtendedAssembler *assembler);
165
166    static void PushCallArgs2AndDispatch(ExtendedAssembler *assembler);
167
168    static void PushCallArg1AndDispatch(ExtendedAssembler *assembler);
169
170    static void PushCallArg0AndDispatch(ExtendedAssembler *assembler);
171
172    static void PushCallThisArg0AndDispatch(ExtendedAssembler *assembler);
173
174    static void PushCallThisArg1AndDispatch(ExtendedAssembler *assembler);
175
176    static void PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler);
177
178    static void PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler);
179
180    static void PushCallThisRangeAndDispatchNative(ExtendedAssembler *assembler);
181
182    static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler);
183
184    static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler);
185
186    static void PushNewTargetAndDispatchNative(ExtendedAssembler *assembler);
187
188    static void PushCallNewAndDispatch(ExtendedAssembler *assembler);
189
190    static void PushSuperCallAndDispatch(ExtendedAssembler *assembler);
191
192    static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler);
193
194    static void ResumeRspAndDispatch(ExtendedAssembler *assembler);
195
196    static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler);
197
198    static void ResumeRspAndReturnBaseline([[maybe_unused]] ExtendedAssembler *assembler);
199
200    static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler);
201
202    static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
203
204    static void ResumeRspAndRollback(ExtendedAssembler *assembler);
205
206    static void CallGetter(ExtendedAssembler *assembler);
207
208    static void CallSetter(ExtendedAssembler *assembler);
209
210    static void CallContainersArgs2(ExtendedAssembler *assembler);
211
212    static void CallContainersArgs3(ExtendedAssembler *assembler);
213
214    static void CallReturnWithArgv([[maybe_unused]]ExtendedAssembler *assembler);
215
216    static void ASMFastWriteBarrier(ExtendedAssembler *assembler);
217
218    static void ASMWriteBarrierWithEden(ExtendedAssembler *assembler);
219
220    static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label& needCall);
221private:
222    static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode,
223                             Label *stackOverflow, FrameTransitionType type);
224
225    static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
226    static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
227
228    static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow, FrameTransitionType type);
229
230    static void DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp,
231                             Register acc = INVALID_REG);
232
233    static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
234
235    static bool PushBuiltinFrame(ExtendedAssembler *assembler, Register glue,
236        FrameType type, Register op, Register next);
237
238    static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp,
239        Register op);
240
241    static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register currentSlot,
242        Register callTarget, Register thisObj, Register method, Register pc, Register op);
243
244    static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, FrameTransitionType type);
245
246    static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis,
247        Label *stackOverflow);
248    static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
249                                     Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
250
251    static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs);
252
253    static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField,
254        Register declaredNumArgs);
255
256    static void SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize);
257
258    static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler);
259
260    static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler);
261
262    static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, Register &fpRegister,
263        Register &currentSlotRegister, Register &callTargetRegister, Register &thisRegister, Register &methodRegister,
264        Register &contextRegister, Register &pcRegister, Register &operatorRegister);
265
266    static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue,
267        Register &callTarget, Register &method, Register &pc, Register &temp);
268
269    static void CallNativeEntry(ExtendedAssembler *assembler);
270
271    static void CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin);
272
273    static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
274    static void PreserveMostCall(ExtendedAssembler* assembler);
275    friend class OptimizedCall;
276    friend class BaselineCall;
277};
278
279class BaselineCall : public CommonCall {
280public:
281    /* other call baseline: need to check whether baseline code exists */
282    static void CallArg0AndCheckToBaseline(ExtendedAssembler *assembler);
283    static void CallArg1AndCheckToBaseline(ExtendedAssembler *assembler);
284    static void CallArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
285    static void CallArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
286    static void CallThisArg0AndCheckToBaseline(ExtendedAssembler *assembler);
287    static void CallThisArg1AndCheckToBaseline(ExtendedAssembler *assembler);
288    static void CallThisArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
289    static void CallThisArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
290    static void CallRangeAndCheckToBaseline(ExtendedAssembler *assembler);
291    static void CallNewAndCheckToBaseline(ExtendedAssembler *assembler);
292    static void SuperCallAndCheckToBaseline(ExtendedAssembler *assembler);
293    static void CallThisRangeAndCheckToBaseline(ExtendedAssembler *assembler);
294    /* baseline call other: need to save fp and lr */
295    static void CallArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
296    static void CallArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
297    static void CallArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
298    static void CallArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
299    static void CallThisArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
300    static void CallThisArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
301    static void CallThisArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
302    static void CallThisArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
303    static void CallRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
304    static void CallNewAndDispatchFromBaseline(ExtendedAssembler *assembler);
305    static void SuperCallAndDispatchFromBaseline(ExtendedAssembler *assembler);
306    static void CallThisRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
307    /* baseline call baseline: need to check whether baseline code exists and save fp and lr */
308    static void CallArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
309    static void CallArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
310    static void CallArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
311    static void CallArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
312    static void CallThisArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
313    static void CallThisArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
314    static void CallThisArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
315    static void CallThisArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
316    static void CallRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
317    static void CallNewAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
318    static void SuperCallAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
319    static void CallThisRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
320    /* get baselineBuiltinFp when baselineBuiltin call the others */
321    static void GetBaselineBuiltinFp(ExtendedAssembler *assembler);
322};
323
324}  // namespace panda::ecmascript::x64
325#endif  // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
326