• 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_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 
23 namespace panda::ecmascript::aarch64 {
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 using Label = panda::ecmascript::Label;
33 class CommonCall {
34 public:
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};
GetStackArgOffSetToFp(unsigned argId)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 
80 class OptimizedCall : public CommonCall {
81 public:
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);
113 private:
114     static void DeoptEnterAsmInterpOrBaseline(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 
139 class OptimizedFastCall : public CommonCall {
140 public:
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 
150 class AsmInterpreterCall : public CommonCall {
151 public:
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 CallGetterToBaseline(ExtendedAssembler *assembler);
217 
218     static void CallSetterToBaseline(ExtendedAssembler *assembler);
219 
220     static void CallContainersArgs2ToBaseline(ExtendedAssembler *assembler);
221 
222     static void CallContainersArgs3ToBaseline(ExtendedAssembler *assembler);
223 
224     static void CallReturnWithArgvToBaseline(ExtendedAssembler *assembler);
225 
226     static void ASMFastWriteBarrier(ExtendedAssembler *assembler);
227 
228     static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label& needCall);
229 private:
230     static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode,
231                              Label *stackOverflow, FrameTransitionType type);
232 
233     static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
234     static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
235 
236     static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow, FrameTransitionType type);
237 
238     static void DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp,
239                              Register acc = INVALID_REG);
240 
241     static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
242 
243     static bool PushBuiltinFrame(ExtendedAssembler *assembler, Register glue,
244         FrameType type, Register op, Register next);
245 
246     static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp,
247         Register op);
248 
249     static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register currentSlot,
250         Register callTarget, Register thisObj, Register method, Register pc, Register op);
251 
252     static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, FrameTransitionType type);
253 
254     static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis,
255         Label *stackOverflow);
256     static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
257                                      Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
258 
259     static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs);
260 
261     static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField,
262         Register declaredNumArgs);
263 
264     static void SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize);
265 
266     static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler);
267 
268     static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler);
269 
270     static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, Register &fpRegister,
271         Register &currentSlotRegister, Register &callTargetRegister, Register &thisRegister, Register &methodRegister,
272         Register &contextRegister, Register &pcRegister, Register &operatorRegister);
273 
274     static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue,
275         Register &callTarget, Register &method, Register &pc, Register &temp);
276 
277     static void CallNativeEntry(ExtendedAssembler *assembler, bool isJsProxy);
278 
279     static void CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin);
280 
281     static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
282     static void PreserveMostCall(ExtendedAssembler* assembler);
283     friend class OptimizedCall;
284     friend class BaselineCall;
285 };
286 
287 class BaselineCall : public CommonCall {
288 public:
289     /* other call baseline: need to check whether baseline code exists */
290     static void CallArg0AndCheckToBaseline(ExtendedAssembler *assembler);
291     static void CallArg1AndCheckToBaseline(ExtendedAssembler *assembler);
292     static void CallArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
293     static void CallArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
294     static void CallThisArg0AndCheckToBaseline(ExtendedAssembler *assembler);
295     static void CallThisArg1AndCheckToBaseline(ExtendedAssembler *assembler);
296     static void CallThisArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
297     static void CallThisArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
298     static void CallRangeAndCheckToBaseline(ExtendedAssembler *assembler);
299     static void CallNewAndCheckToBaseline(ExtendedAssembler *assembler);
300     static void SuperCallAndCheckToBaseline(ExtendedAssembler *assembler);
301     static void CallThisRangeAndCheckToBaseline(ExtendedAssembler *assembler);
302     /* baseline call other: need to save fp and lr */
303     static void CallArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
304     static void CallArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
305     static void CallArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
306     static void CallArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
307     static void CallThisArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
308     static void CallThisArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
309     static void CallThisArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
310     static void CallThisArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
311     static void CallRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
312     static void CallNewAndDispatchFromBaseline(ExtendedAssembler *assembler);
313     static void SuperCallAndDispatchFromBaseline(ExtendedAssembler *assembler);
314     static void CallThisRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
315     /* baseline call baseline: need to check whether baseline code exists and save fp and lr */
316     static void CallArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
317     static void CallArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
318     static void CallArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
319     static void CallArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
320     static void CallThisArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
321     static void CallThisArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
322     static void CallThisArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
323     static void CallThisArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
324     static void CallRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
325     static void CallNewAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
326     static void SuperCallAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
327     static void CallThisRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
328     /* get baselineBuiltinFp when baselineBuiltin call the others */
329     static void GetBaselineBuiltinFp(ExtendedAssembler *assembler);
330 };
331 
332 }  // namespace panda::ecmascript::x64
333 #endif  // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
334