• 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     static void PushAsmBridgeFrame(ExtendedAssembler *assembler);
50     static void PopAsmBridgeFrame(ExtendedAssembler *assembler);
51 };
52 
53 class OptimizedCall : public CommonCall {
54 public:
55     static void CallRuntime(ExtendedAssembler *assembler);
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 CallBuiltinTrampoline(ExtendedAssembler *assembler, Register temp);
103     static void CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
104                                            Register glue, Register temp);
105     static void RemoveArgv(ExtendedAssembler *assembler, Register temp);
106 
107     friend class OptimizedFastCall;
108 };
109 
110 class OptimizedFastCall : public CommonCall {
111 public:
112     static void OptimizedFastCallEntry(ExtendedAssembler *assembler);
113 
114     static void OptimizedFastCallAndPushArgv(ExtendedAssembler *assembler);
115 
116     static void JSFastCallWithArgV(ExtendedAssembler *assembler);
117 
118     static void JSFastCallWithArgVAndPushArgv(ExtendedAssembler *assembler);
119 };
120 
121 class AsmInterpreterCall : public CommonCall {
122 public:
123     static void GeneratorReEnterAsmInterp(ExtendedAssembler *assembler);
124 
125     static void GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler);
126 
127     static void AsmInterpEntryDispatch(ExtendedAssembler *assembler);
128 
129     static void AsmInterpreterEntry(ExtendedAssembler *assembler);
130 
131     static void PushCallThisRangeAndDispatch(ExtendedAssembler *assembler);
132 
133     static void PushCallRangeAndDispatch(ExtendedAssembler *assembler);
134 
135     static void PushCallArgs3AndDispatch(ExtendedAssembler *assembler);
136 
137     static void PushCallArgs2AndDispatch(ExtendedAssembler *assembler);
138 
139     static void PushCallArg1AndDispatch(ExtendedAssembler *assembler);
140 
141     static void PushCallArg0AndDispatch(ExtendedAssembler *assembler);
142 
143     static void PushCallThisArg0AndDispatch(ExtendedAssembler *assembler);
144 
145     static void PushCallThisArg1AndDispatch(ExtendedAssembler *assembler);
146 
147     static void PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler);
148 
149     static void PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler);
150 
151     static void PushCallNewAndDispatch(ExtendedAssembler *assembler);
152 
153     static void PushSuperCallAndDispatch(ExtendedAssembler *assembler);
154 
155     static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler);
156 
157     static void PushNewTargetAndDispatchNative(ExtendedAssembler *assembler);
158 
159     static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler);
160 
161     static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler);
162 
163     static void ResumeRspAndDispatch(ExtendedAssembler *assembler);
164 
165     static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler);
166 
167     static void ResumeRspAndReturnBaseline([[maybe_unused]] ExtendedAssembler *assembler);
168 
169     static void CallGetter(ExtendedAssembler *assembler);
170 
171     static void CallSetter(ExtendedAssembler *assembler);
172 
173     static void CallContainersArgs2(ExtendedAssembler *assembler);
174 
175     static void CallContainersArgs3(ExtendedAssembler *assembler);
176 
177     static void CallReturnWithArgv(ExtendedAssembler *assembler);
178 
179     static void CallGetterToBaseline(ExtendedAssembler *assembler);
180 
181     static void CallSetterToBaseline(ExtendedAssembler *assembler);
182 
183     static void CallContainersArgs2ToBaseline(ExtendedAssembler *assembler);
184 
185     static void CallContainersArgs3ToBaseline(ExtendedAssembler *assembler);
186 
187     static void CallReturnWithArgvToBaseline(ExtendedAssembler *assembler);
188 
189     static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler);
190 
191     static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);
192 
193     static void ResumeRspAndRollback(ExtendedAssembler *assembler);
194 
195     static void ASMFastWriteBarrier(ExtendedAssembler *assembler);
196 private:
197     static void PushFrameState(ExtendedAssembler *assembler, Register prevSpRegister, Register fpRegister,
198         Register callTargetRegister, Register thisRegister, Register methodRegister, Register pcRegister,
199         Register operatorRegister);
200     static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register prevSpRegister,
201         Register fpRegister, Register callTargetRegister, Register thisRegister, Register methodRegister,
202         Register contextRegister, Register pcRegister, Register operatorRegister);
203     static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler);
204     static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler);
205     static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
206         Register declaredNumArgsRegister);
207     static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callFieldRegister,
208         Register numVregsRegister);
209     static void PushUndefinedWithArgcAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc,
210         Register op1, Register op2, Label *stackOverflow);
211     static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp,
212         Register op);
213     static void ThrowStackOverflowExceptionAndReturnToAsmInterpBridgeFrame(ExtendedAssembler *assembler, Register glue,
214         Register fp, Register op);
215     static void HasPendingException(ExtendedAssembler *assembler, Register threadRegister);
216     static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode,
217                              Label *stackOverflow, FrameTransitionType type);
218     static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
219     static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister);
220     static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow, FrameTransitionType type);
221     static void DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister,
222                              Register callTargetRegister, Register methodRegister, Register accRegister = rInvalid);
223     static void CallNativeEntry(ExtendedAssembler *assembler, bool isJsProxy);
224     static void CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin);
225     static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false);
226     static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode);
227     static bool PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type);
228     static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, FrameTransitionType type);
229     static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);
230     static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
231         Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
232     static void PreserveMostCall(ExtendedAssembler* assembler);
233     static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label &needcall);
234     friend class OptimizedCall;
235     friend class BaselineCall;
236 };
237 
238 class BaselineCall : public CommonCall {
239 public:
240     /* other call baseline: need to check whether baseline code exists */
241     static void CallArg0AndCheckToBaseline(ExtendedAssembler *assembler);
242     static void CallArg1AndCheckToBaseline(ExtendedAssembler *assembler);
243     static void CallArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
244     static void CallArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
245     static void CallThisArg0AndCheckToBaseline(ExtendedAssembler *assembler);
246     static void CallThisArg1AndCheckToBaseline(ExtendedAssembler *assembler);
247     static void CallThisArgs2AndCheckToBaseline(ExtendedAssembler *assembler);
248     static void CallThisArgs3AndCheckToBaseline(ExtendedAssembler *assembler);
249     static void CallRangeAndCheckToBaseline(ExtendedAssembler *assembler);
250     static void CallNewAndCheckToBaseline(ExtendedAssembler *assembler);
251     static void SuperCallAndCheckToBaseline(ExtendedAssembler *assembler);
252     static void CallThisRangeAndCheckToBaseline(ExtendedAssembler *assembler);
253     /* baseline call other: need to save fp and lr */
254     static void CallArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
255     static void CallArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
256     static void CallArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
257     static void CallArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
258     static void CallThisArg0AndDispatchFromBaseline(ExtendedAssembler *assembler);
259     static void CallThisArg1AndDispatchFromBaseline(ExtendedAssembler *assembler);
260     static void CallThisArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler);
261     static void CallThisArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler);
262     static void CallRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
263     static void CallNewAndDispatchFromBaseline(ExtendedAssembler *assembler);
264     static void SuperCallAndDispatchFromBaseline(ExtendedAssembler *assembler);
265     static void CallThisRangeAndDispatchFromBaseline(ExtendedAssembler *assembler);
266     /* baseline call baseline: need to check whether baseline code exists and save fp and lr */
267     static void CallArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
268     static void CallArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
269     static void CallArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
270     static void CallArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
271     static void CallThisArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
272     static void CallThisArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
273     static void CallThisArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
274     static void CallThisArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
275     static void CallRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
276     static void CallNewAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
277     static void SuperCallAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
278     static void CallThisRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler);
279     /* get baselineBuiltinFp when baselineBuiltin call the others */
280     static void GetBaselineBuiltinFp(ExtendedAssembler *assembler);
281 };
282 
283 class JsFunctionArgsConfigFrameScope {
284 public:
285     static constexpr int FRAME_SLOT_SIZE = 8;
JsFunctionArgsConfigFrameScope(ExtendedAssembler * assembler)286     explicit JsFunctionArgsConfigFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
287     {
288         assembler_->Pushq(rbp);
289         assembler_->Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME));
290         // 2: skip jsFunc and frameType
291         assembler_->Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
292         // callee save
293         assembler_->Pushq(r12);
294         assembler_->Pushq(r13);
295         assembler_->Pushq(r14);
296         assembler_->Pushq(rbx);
297         assembler_->Pushq(rax);
298     }
~JsFunctionArgsConfigFrameScope()299     ~JsFunctionArgsConfigFrameScope()
300     {
301         assembler_->Movq(rbp, rsp);
302         assembler_->Addq(-5 * FRAME_SLOT_SIZE, rsp); // -5: get r12 r13 r14 rbx
303         assembler_->Popq(rbx);
304         assembler_->Popq(r14);
305         assembler_->Popq(r13);
306         assembler_->Popq(r12);
307         assembler_->Addq(FRAME_SLOT_SIZE, rsp); // skip frame type
308         assembler_->Pop(rbp);
309         assembler_->Ret();
310     }
311     NO_COPY_SEMANTIC(JsFunctionArgsConfigFrameScope);
312     NO_MOVE_SEMANTIC(JsFunctionArgsConfigFrameScope);
313 private:
314     ExtendedAssembler *assembler_;
315 };
316 
317 class OptimizedUnfoldArgVFrameFrameScope {
318 public:
319     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler * assembler)320     explicit OptimizedUnfoldArgVFrameFrameScope(ExtendedAssembler *assembler) : assembler_(assembler)
321     {
322         assembler_->Pushq(rbp);
323         // construct frame
324         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
325         assembler_->Pushq(assembler_->AvailableRegister2());
326         // 2: skip callSiteSp and frameType
327         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
328         assembler_->Pushq(rbx);
329         assembler_->Pushq(r12); // callee save
330     }
~OptimizedUnfoldArgVFrameFrameScope()331     ~OptimizedUnfoldArgVFrameFrameScope()
332     {
333         assembler_->Movq(rbp, rsp);
334         assembler_->Addq(-4 * FRAME_SLOT_SIZE, rsp); // -4: get r12 rbx
335         assembler_->Popq(r12);
336         assembler_->Popq(rbx);
337         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
338         assembler_->Popq(rbp);
339         assembler_->Ret();
340     }
341     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
342     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrameScope);
343 private:
344     ExtendedAssembler *assembler_;
345 };
346 
347 class OptimizedUnfoldArgVFrameFrame1Scope {
348 public:
349     static constexpr int FRAME_SLOT_SIZE = 8;
OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler * assembler)350     explicit OptimizedUnfoldArgVFrameFrame1Scope(ExtendedAssembler *assembler) : assembler_(assembler)
351     {
352         assembler_->Pushq(rbp);
353         // construct frame
354         assembler_->Pushq(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME));
355         assembler_->Pushq(assembler_->AvailableRegister2());
356         // 2: skip callSiteSp and frameType
357         assembler_->Leaq(Operand(rsp, 2 * FRAME_SLOT_SIZE), rbp);
358         assembler_->Pushq(rbx);
359         assembler_->Pushq(r12); // callee save
360         assembler_->Pushq(r13);
361         assembler_->Pushq(r14); // callee save
362     }
~OptimizedUnfoldArgVFrameFrame1Scope()363     ~OptimizedUnfoldArgVFrameFrame1Scope()
364     {
365         assembler_->Movq(rbp, rsp);
366         assembler_->Addq(-6 * FRAME_SLOT_SIZE, rsp); // -6: get r12 r13 r14 rbx
367         assembler_->Popq(r14);
368         assembler_->Popq(r13);
369         assembler_->Popq(r12);
370         assembler_->Popq(rbx);
371         assembler_->Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip frame type and sp
372         assembler_->Popq(rbp);
373         assembler_->Ret();
374     }
375     NO_COPY_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
376     NO_MOVE_SEMANTIC(OptimizedUnfoldArgVFrameFrame1Scope);
377 private:
378     ExtendedAssembler *assembler_;
379 };
380 }  // namespace panda::ecmascript::x64
381 #endif  // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H
382