1/*
2 * Copyright (c) 2022-2024 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#include "ecmascript/compiler/trampoline/aarch64/common_call.h"
17
18#include "ecmascript/compiler/assembler/assembler.h"
19#include "ecmascript/compiler/argument_accessor.h"
20#include "ecmascript/compiler/rt_call_signature.h"
21#include "ecmascript/deoptimizer/deoptimizer.h"
22#include "ecmascript/ecma_runtime_call_info.h"
23#include "ecmascript/frames.h"
24#include "ecmascript/js_function.h"
25#include "ecmascript/method.h"
26#include "ecmascript/js_thread.h"
27#include "ecmascript/message_string.h"
28#include "ecmascript/runtime_call_id.h"
29
30namespace panda::ecmascript::aarch64 {
31using Label = panda::ecmascript::Label;
32#define __ assembler->
33
34// * uint64_t CallRuntime(uintptr_t glue, uint64_t runtime_id, uint64_t argc, uintptr_t arg0, ...)
35// * webkit_jscc calling convention call runtime_id's runtime function(c-abi)
36// * Arguments:
37//         %x0 - glue
38//
39// * Optimized-leaved-frame layout as the following:
40//         +--------------------------+
41//         |       argv[N-1]          |
42//         |--------------------------|
43//         |       . . . . .          |
44//         |--------------------------|
45//         |       argv[0]            |
46//         +--------------------------+-------------
47//         |       argc               |            ^
48//         |--------------------------|            |
49//         |       RuntimeId          |            |
50//  sp --> |--------------------------|   OptimizedLeaveFrame
51//         |       ret-addr           |            |
52//         |--------------------------|            |
53//         |       prevFp             |            |
54//         |--------------------------|            |
55//         |       frameType          |            v
56//         +--------------------------+-------------
57
58void OptimizedCall::CallRuntime(ExtendedAssembler *assembler)
59{
60    Register glue(X0);
61    Register fp(FP);
62    Register tmp(X19);
63    Register sp(SP);
64    Register argC(X1);
65    Register argV(X2);
66
67    __ BindAssemblerStub(RTSTUB_ID(CallRuntime));
68    __ PushFpAndLr();
69
70    Register frameType(X2);
71    // construct Leave Frame and callee save
72    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::LEAVE_FRAME)));
73    // 2 : 2 means pairs
74    __ Stp(tmp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
75    __ Add(fp, sp, Immediate(2 * FRAME_SLOT_SIZE));  // 2 : 2 means pairs
76    __ Str(fp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
77
78    // load runtime trampoline address
79    Register rtfunc(X19);
80    __ Ldr(tmp, MemoryOperand(fp, GetStackArgOffSetToFp(0)));  // 0: the first arg id
81    // 3 : 3 means 2 << 3 = 8
82    __ Add(tmp, glue, Operand(tmp, LSL, 3));
83    __ Ldr(rtfunc, MemoryOperand(tmp, JSThread::GlueData::GetRTStubEntriesOffset(false)));
84    __ Ldr(argC, MemoryOperand(fp, GetStackArgOffSetToFp(1)));  // 1: the second arg id
85    __ Add(argV, fp, Immediate(GetStackArgOffSetToFp(2)));  // 2: the third arg id
86    __ Blr(rtfunc);
87
88    // callee restore
89    // 0 : 0 restore size
90    __ Ldr(tmp, MemoryOperand(sp, 0));
91
92    // descontruct frame
93    // 2 :2 means stack frame slot size
94    __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
95    __ RestoreFpAndLr();
96    __ Ret();
97}
98
99void OptimizedCall::IncreaseStackForArguments(ExtendedAssembler *assembler, Register argc, Register currentSp,
100                                              int64_t numExtraArgs)
101{
102    Register sp(SP);
103    __ Mov(currentSp, sp);
104    if (numExtraArgs > 0) {
105        // add extra aguments, numArgs
106        __ Add(argc, argc, Immediate(numExtraArgs));
107    }
108    __ Sub(currentSp, currentSp, Operand(argc, UXTW, FRAME_SLOT_SIZE_LOG2));
109    Label aligned;
110    __ Tst(currentSp, LogicalImmediate::Create(0xf, RegXSize));  // 0xf: 0x1111
111    __ B(Condition::EQ, &aligned);
112    __ Sub(currentSp, currentSp, Immediate(FRAME_SLOT_SIZE));
113    __ Bind(&aligned);
114    __ Mov(sp, currentSp);
115    __ Add(currentSp, currentSp, Operand(argc, UXTW, FRAME_SLOT_SIZE_LOG2));
116}
117
118// * uint64_t JSFunctionEntry(uintptr_t glue, uint32_t actualNumArgs, const JSTaggedType argV[], uintptr_t prevFp,
119//                            size_t callType)
120// * Arguments:
121//        %x0 - glue
122//        %x1 - actualNumArgs
123//        %x2 - argV
124//        %x3 - prevFp
125//        %x4 - needPushArgv
126//
127// * The JSFunctionEntry Frame's structure is illustrated as the following:
128//          +--------------------------+
129//          |      . . . . . .         |
130//  sp ---> +--------------------------+ -----------------
131//          |        prevFP            |                 ^
132//          |--------------------------|                 |
133//          |       frameType          |      JSFunctionEntryFrame
134//          |--------------------------|                 |
135//          |    preLeaveFrameFp       |                 v
136//          +--------------------------+ -----------------
137
138void OptimizedCall::JSFunctionEntry(ExtendedAssembler *assembler)
139{
140    __ BindAssemblerStub(RTSTUB_ID(JSFunctionEntry));
141    Register glueReg(X0);
142    Register argV(X2);
143    Register prevFpReg(X3);
144    Register needPushArgv(X4);
145    Register sp(SP);
146    Register tmpArgV(X7);
147    Label lJSCallWithArgVAndPushArgv;
148    Label lPopFrame;
149
150    PushJSFunctionEntryFrame (assembler, prevFpReg);
151    __ Mov(Register(X6), needPushArgv);
152    __ Mov(tmpArgV, argV);
153    __ Mov(Register(X20), glueReg);
154    __ Ldr(Register(X2), MemoryOperand(tmpArgV, 0));
155    __ Ldr(Register(X3), MemoryOperand(tmpArgV, FRAME_SLOT_SIZE));
156    __ Ldr(Register(X4), MemoryOperand(tmpArgV, DOUBLE_SLOT_SIZE));
157    __ Add(tmpArgV, tmpArgV, Immediate(TRIPLE_SLOT_SIZE));
158    __ Mov(Register(X5), tmpArgV);
159    __ Cmp(Register(X6), Immediate(1));
160    __ B(Condition::EQ, &lJSCallWithArgVAndPushArgv);
161    __ CallAssemblerStub(RTSTUB_ID(JSCallWithArgV), false);
162    __ B(&lPopFrame);
163
164    __ Bind(&lJSCallWithArgVAndPushArgv);
165    __ CallAssemblerStub(RTSTUB_ID(JSCallWithArgVAndPushArgv), false);
166    __ Bind(&lPopFrame);
167    __ Mov(Register(X2), Register(X20));
168    PopJSFunctionEntryFrame(assembler, Register(X2));
169    __ Ret();
170}
171
172// * uint64_t OptimizedCallAndPushArgv(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, JSTaggedType new,
173//                   JSTaggedType this, arg[0], arg[1], arg[2], ..., arg[N-1])
174// * webkit_jscc calling convention call js function()
175//
176// * OptimizedJSFunctionFrame layout description as the following:
177//               +--------------------------+
178//               |        arg[N-1]          |
179//               +--------------------------+
180//               |       ...                |
181//               +--------------------------+
182//               |       arg[1]             |
183//               +--------------------------+
184//               |       arg[0]             |
185//               +--------------------------+
186//               |       this               |
187//               +--------------------------+
188//               |       new-target         |
189//               +--------------------------+
190//               |       call-target        |
191//               +--------------------------+
192//               |       argv               |
193//               +--------------------------+
194//               |       argc               |
195//     sp ---->  |--------------------------| ---------------
196//               |       returnAddr         |               ^
197//               |--------------------------|               |
198//               |       callsiteFp         |               |
199//               |--------------------------|   OptimizedJSFunctionFrame
200//               |       frameType          |               |
201//               |--------------------------|               |
202//               |       call-target        |               v
203//               +--------------------------+ ---------------
204void OptimizedCall::OptimizedCallAndPushArgv(ExtendedAssembler *assembler)
205{
206    __ BindAssemblerStub(RTSTUB_ID(OptimizedCallAndPushArgv));
207    Register sp(SP);
208    Register jsfunc(X7);
209    Register method(X6);
210    Register expectedNumArgs(X1);
211    Register actualNumArgs(X2);
212    Register codeAddr(X3);
213    Register argV(X4);
214
215    auto funcSlotOffSet = kungfu::ArgumentAccessor::GetExtraArgsNum();
216    __ Ldr(jsfunc, MemoryOperand(sp, funcSlotOffSet * FRAME_SLOT_SIZE));
217    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
218    __ Ldr(codeAddr, MemoryOperand(jsfunc, JSFunction::CODE_ENTRY_OFFSET));
219    __ Ldr(expectedNumArgs, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
220    __ Lsr(expectedNumArgs, expectedNumArgs, MethodLiteral::NumArgsBits::START_BIT);
221    __ And(expectedNumArgs, expectedNumArgs,
222        LogicalImmediate::Create(
223            MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize));
224    __ Add(expectedNumArgs, expectedNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
225
226    __ Add(argV, sp, Immediate(funcSlotOffSet * FRAME_SLOT_SIZE));  // skip numArgs and argv
227    __ Ldr(actualNumArgs, MemoryOperand(sp, 0));
228
229    Register glue(X0);
230    Register currentSp(X5);
231    Label copyArguments;
232    Label invokeCompiledJSFunction;
233
234    // construct frame
235    PushOptimizedArgsConfigFrame(assembler);
236    Register argC(X7);
237    __ Cmp(expectedNumArgs, actualNumArgs);
238    __ CMov(argC, expectedNumArgs, actualNumArgs, Condition::HI);
239    IncreaseStackForArguments(assembler, argC, currentSp, static_cast<int64_t>(CommonArgIdx::ACTUAL_ARGV));
240    {
241        TempRegister1Scope scope1(assembler);
242        TempRegister2Scope scope2(assembler);
243        Register tmp = __ TempRegister1();
244        Register undefinedValue = __ TempRegister2();
245        __ Subs(tmp, expectedNumArgs, actualNumArgs);
246        __ B(Condition::LS, &copyArguments);
247        PushUndefinedWithArgc(assembler, glue, tmp, undefinedValue, currentSp, nullptr, nullptr);
248    }
249    __ Bind(&copyArguments);
250    __ Cbz(actualNumArgs, &invokeCompiledJSFunction);
251    {
252        TempRegister1Scope scope1(assembler);
253        TempRegister2Scope scope2(assembler);
254        Register argc = __ TempRegister1();
255        Register argValue = __ TempRegister2();
256        __ Mov(argc, actualNumArgs);
257        PushArgsWithArgv(assembler, glue, argc, argV, argValue, currentSp, &invokeCompiledJSFunction, nullptr);
258    }
259    __ Bind(&invokeCompiledJSFunction);
260    {
261        __ Mov(Register(X19), expectedNumArgs);
262        __ Str(currentSp, MemoryOperand(sp, FRAME_SLOT_SIZE));
263        __ Str(actualNumArgs, MemoryOperand(sp, 0)); // argv, argc
264        __ Blr(codeAddr);
265    }
266
267    // pop argV argC
268    // 3 : 3 means argC * 8
269    __ Ldr(actualNumArgs, MemoryOperand(sp, 0));
270    PopJSFunctionArgs(assembler, Register(X19), actualNumArgs);
271    // pop prevLeaveFrameFp to restore thread->currentFrame_
272    PopOptimizedArgsConfigFrame(assembler);
273    __ Ret();
274}
275
276void OptimizedCall::OptimizedCallAsmInterpreter(ExtendedAssembler *assembler)
277{
278    Label target;
279    PushAsmInterpBridgeFrame(assembler);
280    __ Bl(&target);
281    PopAsmInterpBridgeFrame(assembler);
282    __ Ret();
283    __ Bind(&target);
284    {
285        AsmInterpreterCall::JSCallCommonEntry(assembler, JSCallMode::CALL_FROM_AOT,
286                                              FrameTransitionType::OTHER_TO_OTHER);
287    }
288}
289
290// * uint64_t CallBuiltinTrampoline(uintptr_t glue, uintptr_t codeAddress, uint32_t argc, ...)
291// * webkit_jscc calling convention call runtime_id's runtime function(c-abi)
292// * Argument:
293//           %x0: glue
294//
295// * Construct Native Leave Frame Layout:
296//          +--------------------------+
297//          |       argv[N-1]          |
298//          +--------------------------+
299//          |      . . . . . .         |
300//          +--------------------------+
301//          |      argv[3]=a0          |
302//          +--------------------------+
303//          |      argv[2]=this        |
304//          +--------------------------+
305//          |   argv[1]=new-target     |
306//          +--------------------------+
307//          |   argv[0]=call-target    |
308//          +--------------------------+ -----------------
309//          |       argc               |                 ^
310//          |--------------------------|                 |
311//          |       thread             |                 |
312//          |--------------------------|                 |
313//          |       returnAddr         |    OptimizedBuiltinLeaveFrame
314//  sp ---> |--------------------------|                 |
315//          |       callsiteFp         |                 |
316//          |--------------------------|                 |
317//          |       frameType          |                 v
318//          +--------------------------+ -----------------
319
320void OptimizedCall::CallBuiltinTrampoline(ExtendedAssembler *assembler)
321{
322    Register glue(X0);
323    Register sp(SP);
324    Register nativeFuncAddr(X4);
325    Register temp(X1);
326
327    // remove argv
328    __ Ldr(temp, MemoryOperand(sp, 0));
329    __ Stp(glue, temp, MemoryOperand(sp, 0));   // argc, glue
330    // returnAddr, callsiteFp
331    __ Stp(Register(X29), Register(X30), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
332    __ Mov(temp, sp);
333    __ Str(temp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); // rbp
334    __ Mov(Register(X29), temp); // rbp
335    __ Mov(temp, Immediate(static_cast<int32_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME)));
336    __ Stp(Register(Zero), temp, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); // frameType, argv
337    __ Add(Register(X0), sp, Immediate(QUADRUPLE_SLOT_SIZE));
338    __ Blr(nativeFuncAddr);
339
340    __ Mov(sp, Register(FP));
341    __ Ldp(Register(X29), Register(X30), MemoryOperand(sp, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
342    __ Ldr(temp, MemoryOperand(sp, FRAME_SLOT_SIZE)); // argc
343    __ Stp(temp, Register(Zero), MemoryOperand(sp, 0)); // argv, argc
344
345    __ Ret();
346}
347
348// * uint64_t CallBuiltinConstructorStub(uintptr_t glue, uintptr_t codeAddress, uint32_t argc, ...)
349// * webkit_jscc calling convention call runtime_id's runtime function(c-abi)
350//
351// * Construct Native Leave Frame Layout:
352//          +--------------------------+
353//          |       argv[N-1]          |
354//          +--------------------------+
355//          |      . . . . . .         |
356//          +--------------------------+
357//          |      argv[3]=a0          |
358//          +--------------------------+
359//          |      argv[2]=this        |
360//          +--------------------------+
361//          |   argv[1]=new-target     |
362//          +--------------------------+
363//          |   argv[0]=call-target    |
364//          +--------------------------+ -----------------
365//          |       argc               |                 ^
366//          |--------------------------|                 |
367//          |       thread             |                 |
368//          |--------------------------|                 |
369//          |       returnAddr         |    OptimizedBuiltinLeaveFrame
370//  sp ---> |--------------------------|                 |
371//          |       callsiteFp         |                 |
372//          |--------------------------|                 |
373//          |       frameType          |                 v
374//          +--------------------------+ -----------------
375
376void OptimizedCall::CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
377                                               Register glue, Register temp)
378{
379    Register sp(SP);
380
381    __ Ldr(temp, MemoryOperand(sp, 0));
382    __ Stp(glue, temp, MemoryOperand(sp, 0));   // argc, glue
383    // returnAddr, callsiteFp
384    __ Stp(Register(X29), Register(X30), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
385    __ Mov(temp, sp);
386    __ Mov(Register(X29), temp); // rbp
387    __ Mov(temp, Immediate(static_cast<int32_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME)));
388    __ Stp(Register(Zero), temp, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); // frameType, argv
389    __ Add(argv, sp, Immediate(NONUPLE_SLOT_SIZE));
390    __ Blr(builtinStub);
391
392    __ Mov(sp, Register(FP));
393    __ Ldp(Register(X29), Register(X30), MemoryOperand(sp, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
394    __ Ldr(temp, MemoryOperand(sp, FRAME_SLOT_SIZE)); // argc
395    __ Stp(temp, Register(Zero), MemoryOperand(sp, 0)); // argv, argc
396
397    __ Ret();
398}
399
400// * uint64_t JSCall(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, JSTaggedType new,
401//                   JSTaggedType this, arg[0], arg[1], arg[2], ..., arg[N-1])
402// * webkit_jscc calling convention call js function()
403//
404// * OptimizedJSFunctionFrame layout description as the following:
405//               +--------------------------+
406//               |        arg[N-1]          |
407//               +--------------------------+
408//               |       ...                |
409//               +--------------------------+
410//               |       arg[1]             |
411//               +--------------------------+
412//               |       arg[0]             |
413//               +--------------------------+
414//               |       this               |
415//               +--------------------------+
416//               |       new-target         |
417//               +--------------------------+
418//               |       call-target        |
419//               +--------------------------+
420//               |       argv               |
421//               |--------------------------|
422//               |       argc               |
423//      sp ----> |--------------------------| ---------------
424//               |       returnAddr         |               ^
425//               |--------------------------|               |
426//               |       callsiteFp         |               |
427//               |--------------------------|   OptimizedJSFunctionFrame
428//               |       frameType          |               |
429//               |--------------------------|               |
430//               |       call-target        |               v
431//               +--------------------------+ ---------------
432
433void OptimizedCall::GenJSCall(ExtendedAssembler *assembler, bool isNew)
434{
435    Register jsfunc(X1);
436    Register sp(SP);
437    __ Ldr(jsfunc, MemoryOperand(sp, DOUBLE_SLOT_SIZE)); // skip 2: argc, argv
438    JSCallInternal(assembler, jsfunc, isNew);
439}
440
441void OptimizedCall::JSCallNew(ExtendedAssembler *assembler)
442{
443    __ BindAssemblerStub(RTSTUB_ID(JSCallNew));
444    GenJSCall(assembler, true);
445}
446
447void OptimizedCall::JSCall(ExtendedAssembler *assembler)
448{
449    __ BindAssemblerStub(RTSTUB_ID(JSCall));
450    GenJSCall(assembler, false);
451}
452
453void OptimizedCall::JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew)
454{
455    Register sp(SP);
456    Register glue(X0);
457    Register taggedValue(X2);
458    Label nonCallable;
459    Label notJSFunction;
460    JSCallCheck(assembler, jsfunc, taggedValue, &nonCallable, &notJSFunction);
461
462    Register method(X2);
463    Register callField(X3);
464    Register actualArgC(X4);
465    Label callNativeMethod;
466    Label lCallConstructor;
467    Label lCallBuiltinStub;
468    Label lCallNativeCpp;
469    Label lNotClass;
470
471    __ Ldr(Register(X5), MemoryOperand(jsfunc, 0));
472    __ Ldr(Register(X5), MemoryOperand(Register(X5), JSHClass::BIT_FIELD_OFFSET));
473    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
474    __ Ldr(actualArgC, MemoryOperand(sp, 0));
475    __ Ldr(callField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
476    __ Tbnz(callField, MethodLiteral::IsNativeBit::START_BIT, &callNativeMethod);
477    if (!isNew) {
478        __ Tbz(Register(X5), JSHClass::IsClassConstructorOrPrototypeBit::START_BIT, &lNotClass);
479        __ Tbnz(Register(X5), JSHClass::ConstructorBit::START_BIT, &lCallConstructor);
480    }
481    __ Bind(&lNotClass);
482    {
483        Register argV(X5);
484        // skip argc and argv
485        __ Add(argV, sp, Immediate(kungfu::ArgumentAccessor::GetExtraArgsNum() * FRAME_SLOT_SIZE));
486        // asm interpreter argV = argv + 24
487        __ Add(argV, argV, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE));
488        __ Sub(actualArgC, actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()));
489        OptimizedCallAsmInterpreter(assembler);
490    }
491
492    __ Bind(&callNativeMethod);
493    {
494        Register nativeFuncAddr(X4);
495        if (!isNew) {
496            __ Tbz(callField, MethodLiteral::IsFastBuiltinBit::START_BIT, &lCallNativeCpp);
497            // 3 : 3 means call0 call1 call2 call3
498            __ Cmp(actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() + 3));
499            __ B(Condition::LE, &lCallBuiltinStub);
500        } else {
501            __ Tbnz(callField, MethodLiteral::IsFastBuiltinBit::START_BIT, &lCallBuiltinStub);
502        }
503        __ Bind(&lCallNativeCpp);
504        __ Ldr(nativeFuncAddr, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
505        CallBuiltinTrampoline(assembler);
506    }
507
508    __ Bind(&lCallBuiltinStub);
509    {
510        TempRegister1Scope scope1(assembler);
511        Register builtinStub = __ TempRegister1();
512        __ Ldr(Register(X5), MemoryOperand(method, Method::EXTRA_LITERAL_INFO_OFFSET));  // get extra literal
513        __ And(Register(X5).W(), Register(X5).W(), LogicalImmediate::Create(0xff, RegWSize));
514        if (!isNew) {
515            __ Cmp(Register(X5).W(), Immediate(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST));
516            __ B(Condition::GE, &lCallNativeCpp);
517        }
518        __ Add(builtinStub, glue, Operand(Register(X5).W(), UXTW, FRAME_SLOT_SIZE_LOG2));
519        __ Ldr(builtinStub, MemoryOperand(builtinStub, JSThread::GlueData::GetBuiltinsStubEntriesOffset(false)));
520
521        __ Ldr(Register(X1), MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
522        __ Ldr(Register(X2), MemoryOperand(sp, DOUBLE_SLOT_SIZE));  // get jsfunc
523        __ Ldr(Register(X3), MemoryOperand(sp, TRIPLE_SLOT_SIZE));  // get newtarget
524        __ Ldr(Register(X4), MemoryOperand(sp, QUADRUPLE_SLOT_SIZE));  // get this
525        __ Ldr(Register(X5), MemoryOperand(sp, 0));  // get number args
526        __ Sub(Register(X5), Register(X5), Immediate(NUM_MANDATORY_JSFUNC_ARGS));
527        if (!isNew) {
528            Label lCall0;
529            Label lCall1;
530            Label lCall2;
531            Label lCall3;
532            Label lTailCall;
533            Register fp(X29);
534            __ Cmp(Register(X5), Immediate(0));
535            __ B(Condition::EQ, &lCall0);
536            __ Cmp(Register(X5), Immediate(1));
537            __ B(Condition::EQ, &lCall1);
538            __ Cmp(Register(X5), Immediate(2));  // 2: 2 args
539            __ B(Condition::EQ, &lCall2);
540            __ Cmp(Register(X5), Immediate(3));  // 3: 3 args
541            __ B(Condition::EQ, &lCall3);
542
543            __ Bind(&lCall0);
544            {
545                __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED));
546                __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
547                __ Str(Register(X7), MemoryOperand(sp, 0));  // reset arg2's position
548                __ B(&lTailCall);
549            }
550
551            __ Bind(&lCall1);
552            {
553                __ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE));
554                __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));  // reset x7
555                __ Str(Register(X7), MemoryOperand(sp, 0));  // reset arg2's position
556                __ B(&lTailCall);
557            }
558
559            __ Bind(&lCall2);
560            {
561                __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
562                __ Str(Register(X7), MemoryOperand(sp, 0));  // reset arg2's position
563                __ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE));
564                __ B(&lTailCall);
565            }
566
567            __ Bind(&lCall3);
568            __ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE));  // get arg0 arg1
569            PushAsmBridgeFrame(assembler);
570            {
571                // push arg2 and call
572                TempRegister2Scope scope2(assembler);
573                Register arg2 = __ TempRegister2();
574                __ Ldr(arg2, MemoryOperand(fp, NONUPLE_SLOT_SIZE));
575                __ Stp(arg2, Register(X8), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
576                __ Blr(builtinStub);
577                __ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE));
578            }
579            PopAsmBridgeFrame(assembler);
580            __ Ret();
581            __ Bind(&lTailCall);
582            {
583                __ Br(builtinStub);
584            }
585        } else {
586            Register argv(X6);
587            TempRegister2Scope scope2(assembler);
588            Register temp = __ TempRegister2();
589            CallBuiltinConstructorStub(assembler, builtinStub, argv, glue, temp);
590        }
591    }
592
593    Label jsBoundFunction;
594    Label jsProxy;
595    __ Bind(&notJSFunction);
596    {
597        Register bitfield(X2);
598        Register jstype2(X5, W);
599        __ And(jstype2, bitfield.W(), LogicalImmediate::Create(0xff, RegWSize));
600        __ Cmp(jstype2, Immediate(static_cast<int64_t>(JSType::JS_BOUND_FUNCTION)));
601        __ B(Condition::EQ, &jsBoundFunction);
602        __ Cmp(jstype2, Immediate(static_cast<int64_t>(JSType::JS_PROXY)));
603        __ B(Condition::EQ, &jsProxy);
604        __ Ret();
605    }
606
607    __ Bind(&jsBoundFunction);
608    {
609        JSBoundFunctionCallInternal(assembler, glue, actualArgC, jsfunc, RTSTUB_ID(JSCall));
610    }
611    __ Bind(&jsProxy);
612    {
613        __ Ldr(method, MemoryOperand(jsfunc, JSProxy::METHOD_OFFSET));
614        __ Ldr(callField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
615        __ Ldr(actualArgC, MemoryOperand(sp, 0));
616        __ B(&callNativeMethod);
617    }
618    __ Bind(&nonCallable);
619    {
620        ThrowNonCallableInternal(assembler, sp);
621    }
622    __ Bind(&lCallConstructor);
623    {
624        Register frameType(X6);
625        __ PushFpAndLr();
626        __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)));
627        // 2 : 2 means pair
628        __ Stp(Register(Zero), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
629        __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
630        Register argC(X5);
631        Register runtimeId(X6);
632        __ Mov(argC, Immediate(0));
633        __ Mov(runtimeId, Immediate(RTSTUB_ID(ThrowCallConstructorException)));
634        // 2 : 2 means pair
635        __ Stp(runtimeId, argC, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
636        __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
637        // 4 : 4 means stack slot
638        __ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE));
639        __ RestoreFpAndLr();
640        __ Ret();
641    }
642}
643
644// After the callee function of common aot call deopt, use this bridge to deal with this aot call.
645// calling convention: webkit_jsc
646// Input structure:
647// %X0 - glue
648// stack:
649// +--------------------------+
650// |       arg[N-1]           |
651// +--------------------------+
652// |       ...                |
653// +--------------------------+
654// |       arg[1]             |
655// +--------------------------+
656// |       arg[0]             |
657// +--------------------------+
658// |       this               |
659// +--------------------------+
660// |       new-target         |
661// +--------------------------+
662// |       call-target        |
663// |--------------------------|
664// |       argv               |
665// |--------------------------|
666// |       argc               |
667// +--------------------------+ <---- sp
668void OptimizedCall::AOTCallToAsmInterBridge(ExtendedAssembler *assembler)
669{
670    __ BindAssemblerStub(RTSTUB_ID(AOTCallToAsmInterBridge));
671    Register sp(SP);
672    // params of c++ calling convention
673    Register glue(X0);
674    Register jsfunc(X1);
675    Register method(X2);
676    Register callField(X3);
677    Register actualArgC(X4);
678    Register argV(X5);
679
680    __ Ldr(jsfunc, MemoryOperand(sp, DOUBLE_SLOT_SIZE));
681    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
682    __ Ldr(callField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
683    __ Ldr(actualArgC, MemoryOperand(sp, 0));
684    // skip argc
685    __ Add(argV, sp, Immediate(kungfu::ArgumentAccessor::GetExtraArgsNum() * FRAME_SLOT_SIZE));
686    // asm interpreter argV = argv + 24
687    __ Add(argV, argV, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE));
688    __ Sub(actualArgC, actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()));
689    OptimizedCallAsmInterpreter(assembler);
690}
691
692// After the callee function of fast aot call deopt, use this bridge to deal with this fast aot call.
693// Notice: no argc and new-target params compared with not-fast aot call because these params are not needed
694// by bytecode-analysis
695// Intruduction: use expected argc as actual argc below for these reasons:
696// 1) when expected argc == actual argc, pass.
697// 2) when expected argc > actual argc, undefineds have been pushed in OptimizedFastCallAndPushArgv.
698// 3) when expected argc < actual argc, redundant params are useless according to bytecode-analysis, just abandon them.
699// calling convention: c++ calling convention
700// Input structure:
701// %X0 - glue
702// %X1 - call-target
703// %X2 - this
704// %X3 - arg0
705// %X4 - arg1
706// %X5 - arg2
707// %X6 - arg3
708// %X7 - arg4
709// stack:
710// +--------------------------+
711// |        arg[N-1]          |
712// +--------------------------+
713// |       ...                |
714// +--------------------------+
715// |       arg[5]             |
716// +--------------------------+ <---- sp
717void OptimizedCall::FastCallToAsmInterBridge(ExtendedAssembler *assembler)
718{
719    __ BindAssemblerStub(RTSTUB_ID(FastCallToAsmInterBridge));
720
721    // Add a bridge frame to protect the stack map, because args will be put on the stack to construct argv on stack
722    // and the AsmInterpBridgeFrame pushed below cannot protect the stack map anymore.
723    PushAsmBridgeFrame(assembler);
724
725    Register sp(SP);
726    // Input
727    Register glue(X0);
728    Register jsfunc(X1);
729    Register thisReg(X2);
730
731    Register tempArgc = __ AvailableRegister1();
732    {
733        TempRegister2Scope scope2(assembler);
734        Register tempMethod = __ TempRegister2();
735
736        __ Ldr(tempMethod, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
737        __ Ldr(tempArgc, MemoryOperand(tempMethod, Method::CALL_FIELD_OFFSET));
738        __ Lsr(tempArgc, tempArgc, MethodLiteral::NumArgsBits::START_BIT);
739        __ And(tempArgc, tempArgc,
740            LogicalImmediate::Create(
741                MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize));
742    }
743    {
744        TempRegister1Scope scope1(assembler);
745        Register startSp = __ TempRegister1();
746        __ Mov(startSp, sp);
747
748        Label lCall0;
749        Label lCall1;
750        Label lCall2;
751        Label lCall3;
752        Label lCall4;
753        Label lCall5;
754        Label lPushCommonRegs;
755
756        __ Cmp(tempArgc, Immediate(0));
757        __ B(Condition::EQ, &lCall0);
758        __ Cmp(tempArgc, Immediate(1));
759        __ B(Condition::EQ, &lCall1);
760        __ Cmp(tempArgc, Immediate(2));  // 2: 2 args
761        __ B(Condition::EQ, &lCall2);
762        __ Cmp(tempArgc, Immediate(3));  // 3: 3 args
763        __ B(Condition::EQ, &lCall3);
764        __ Cmp(tempArgc, Immediate(4));  // 4: 4 args
765        __ B(Condition::EQ, &lCall4);
766        __ Cmp(tempArgc, Immediate(5));  // 5: 5 args
767        __ B(Condition::EQ, &lCall5);
768        // default: more than 5 args
769        {
770            TempRegister2Scope scope2(assembler);
771            Register onStackArgs = __ TempRegister2();
772            Register op1 = __ AvailableRegister2();
773            Register op2 = __ AvailableRegister3();
774
775            // skip bridge frame, return addr and a callee save
776            __ Add(onStackArgs, sp, Immediate(QUADRUPLE_SLOT_SIZE));
777            __ Sub(tempArgc, tempArgc, Immediate(5));  // 5: the first 5 args are not on stack
778            Register arg4(X7);
779            PushArgsWithArgvInPair(assembler, tempArgc, onStackArgs, arg4, op1, op2, &lCall4);
780        }
781
782        __ Bind(&lCall0);
783        {
784            __ B(&lPushCommonRegs);
785        }
786
787        __ Bind(&lCall1);
788        {
789            __ Stp(Register(X3), Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
790            __ B(&lPushCommonRegs);
791        }
792
793        __ Bind(&lCall2);
794        {
795            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
796            __ B(&lPushCommonRegs);
797        }
798
799        __ Bind(&lCall3);
800        {
801            __ Stp(Register(X5), Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
802            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
803            __ B(&lPushCommonRegs);
804        }
805
806        __ Bind(&lCall4);
807        {
808            __ Stp(Register(X5), Register(X6), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
809            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
810            __ B(&lPushCommonRegs);
811        }
812
813        __ Bind(&lCall5);
814        {
815            __ Stp(Register(X7), Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
816            __ Stp(Register(X5), Register(X6), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
817            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
818            __ B(&lPushCommonRegs);
819        }
820
821        __ Bind(&lPushCommonRegs);
822        {
823            Register newTarget(X7);
824            __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED));
825            __ Stp(newTarget, thisReg, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
826            __ Stp(startSp, jsfunc, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
827            // fall through
828        }
829    }
830
831    // params of c++ calling convention
832    // glue: X0
833    // jsfunc: X1
834    Register method(X2);
835    Register methodCallField(X3);
836    Register argc(X4);
837    Register argV(X5);
838    // reload and prepare args for JSCallCommonEntry
839    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
840    __ Ldr(methodCallField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
841    __ Mov(argc, methodCallField);
842    __ Lsr(argc, argc, MethodLiteral::NumArgsBits::START_BIT);
843    __ And(argc, argc,
844        LogicalImmediate::Create(
845            MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize));
846    __ Add(argV, sp, Immediate((kungfu::ArgumentAccessor::GetFixArgsNum() + 1) * FRAME_SLOT_SIZE));  // 1: skip startSp
847
848    Label target;
849    PushAsmInterpBridgeFrame(assembler);
850    __ Bl(&target);
851    {
852        PopAsmInterpBridgeFrame(assembler);
853        TempRegister1Scope scope1(assembler);
854        Register startSp = __ TempRegister1();
855        __ Ldp(startSp, Register(Zero), MemoryOperand(sp, ExtendedAssembler::PAIR_SLOT_SIZE, POSTINDEX));
856        __ Mov(sp, startSp);
857        PopAsmBridgeFrame(assembler);
858        __ Ret();
859    }
860    __ Bind(&target);
861    {
862        AsmInterpreterCall::JSCallCommonEntry(assembler, JSCallMode::CALL_FROM_AOT,
863                                              FrameTransitionType::OTHER_TO_OTHER);
864    }
865}
866
867void OptimizedCall::JSCallCheck(ExtendedAssembler *assembler, Register jsfunc, Register taggedValue,
868                                Label *nonCallable, Label *notJSFunction)
869{
870    __ Mov(taggedValue, JSTaggedValue::TAG_MARK);
871    __ Cmp(jsfunc, taggedValue);
872    __ B(Condition::HS, nonCallable);
873    __ Cbz(jsfunc, nonCallable);
874    __ Mov(taggedValue, JSTaggedValue::TAG_SPECIAL);
875    __ And(taggedValue, jsfunc, taggedValue);
876    __ Cbnz(taggedValue, nonCallable);
877
878    Register jshclass(X2);
879    __ Ldr(jshclass, MemoryOperand(jsfunc, JSFunction::HCLASS_OFFSET));
880    Register bitfield(X2);
881    __ Ldr(bitfield, MemoryOperand(jshclass, JSHClass::BIT_FIELD_OFFSET));
882    __ Tbz(bitfield, JSHClass::CallableBit::START_BIT, nonCallable);
883
884    Register jstype(X3, W);
885    __ And(jstype, bitfield, LogicalImmediate::Create(0xFF, RegWSize));
886    // 4 : 4 means JSType::JS_FUNCTION_FIRST
887    __ Sub(jstype, jstype, Immediate(static_cast<int>(JSType::JS_FUNCTION_FIRST)));
888    // 9 : 9 means JSType::JS_FUNCTION_LAST - JSType::JS_FUNCTION_FIRST + 1
889    __ Cmp(jstype, Immediate(static_cast<int>(JSType::JS_FUNCTION_LAST) -
890        static_cast<int>(JSType::JS_FUNCTION_FIRST) + 1));
891    __ B(Condition::HS, notJSFunction);
892}
893
894void OptimizedCall::ThrowNonCallableInternal(ExtendedAssembler *assembler, Register sp)
895{
896    Register frameType(X6);
897    Register taggedMessageId(X5);
898    __ PushFpAndLr();
899    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)));
900    __ Mov(taggedMessageId,
901        Immediate(JSTaggedValue(GET_MESSAGE_STRING_ID(NonCallable)).GetRawData()));
902    // 2 : 2 means pair
903    __ Stp(taggedMessageId, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
904    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
905    Register argC(X5);
906    Register runtimeId(X6);
907    __ Mov(argC, Immediate(1));
908    __ Mov(runtimeId, Immediate(RTSTUB_ID(ThrowTypeError)));
909    // 2 : 2 means pair
910    __ Stp(runtimeId, argC, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
911    __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
912    __ Mov(Register(X0), Immediate(JSTaggedValue::VALUE_EXCEPTION));
913    // 4 : 4 means stack slot
914    __ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE));
915    __ RestoreFpAndLr();
916    __ Ret();
917}
918
919void OptimizedCall::JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register glue,
920                                                Register actualArgC, Register jsfunc, int stubId)
921{
922    // construct frame
923    PushOptimizedArgsConfigFrame(assembler);
924    Register basefp(X29);
925    Register fp = __ AvailableRegister1();
926
927    Register argV(X5);
928    __ Add(argV, basefp, Immediate(GetStackArgOffSetToFp(0))); // 0: first index id
929    __ Ldr(actualArgC, MemoryOperand(argV, 0));
930
931    Register boundLength(X2);
932    Register realArgC(X7, W);
933    Label copyBoundArgument;
934    Label pushCallTarget;
935    Label popArgs;
936    Label slowCall;
937    Label aotCall;
938    Label notClass;
939    // get bound arguments
940    __ Ldr(boundLength, MemoryOperand(jsfunc, JSBoundFunction::BOUND_ARGUMENTS_OFFSET));
941    //  get bound length
942    __ Ldr(boundLength, MemoryOperand(boundLength, TaggedArray::LENGTH_OFFSET));
943    __ Add(realArgC, boundLength.W(), actualArgC.W());
944    __ Mov(Register(X19), realArgC);
945    IncreaseStackForArguments(assembler, realArgC, fp, static_cast<int64_t>(CommonArgIdx::ACTUAL_ARGV));
946    __ Sub(actualArgC.W(), actualArgC.W(), Immediate(NUM_MANDATORY_JSFUNC_ARGS));
947    __ Cmp(actualArgC.W(), Immediate(0));
948    __ B(Condition::EQ, &copyBoundArgument);
949    {
950        TempRegister1Scope scope1(assembler);
951        Register tmp = __ TempRegister1();
952        const int64_t argoffsetSlot = static_cast<int64_t>(CommonArgIdx::FUNC) - 1;
953        __ Add(argV, argV, Immediate((NUM_MANDATORY_JSFUNC_ARGS + argoffsetSlot) * FRAME_SLOT_SIZE));
954        PushArgsWithArgv(assembler, glue, actualArgC, argV, tmp, fp, nullptr, nullptr);
955    }
956    __ Bind(&copyBoundArgument);
957    {
958        Register boundArgs(X4);
959        __ Ldr(boundArgs, MemoryOperand(jsfunc, JSBoundFunction::BOUND_ARGUMENTS_OFFSET));
960        __ Add(boundArgs, boundArgs, Immediate(TaggedArray::DATA_OFFSET));
961        __ Cmp(boundLength.W(), Immediate(0));
962        __ B(Condition::EQ, &pushCallTarget);
963        {
964            TempRegister1Scope scope1(assembler);
965            Register tmp = __ TempRegister1();
966            PushArgsWithArgv(assembler, glue, boundLength, boundArgs, tmp, fp, nullptr, nullptr);
967        }
968    }
969    Register boundTarget(X7);
970    Register newTarget(X6);
971    __ Bind(&pushCallTarget);
972    {
973        Register thisObj(X4);
974        __ Ldr(thisObj, MemoryOperand(jsfunc, JSBoundFunction::BOUND_THIS_OFFSET));
975        __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED));
976        // 2 : 2 means pair
977        __ Stp(newTarget, thisObj, MemoryOperand(fp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
978        __ Ldr(boundTarget, MemoryOperand(jsfunc, JSBoundFunction::BOUND_TARGET_OFFSET));
979        // 2 : 2 means pair
980        __ Stp(argV, boundTarget, MemoryOperand(fp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
981        __ Str(Register(X19), MemoryOperand(fp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
982    }
983    JSCallCheck(assembler, boundTarget, Register(X9), &slowCall, &slowCall);
984    Register hclass = __ AvailableRegister2();
985    __ Ldr(hclass, MemoryOperand(boundTarget, 0));
986    __ Ldr(hclass, MemoryOperand(hclass, JSHClass::BIT_FIELD_OFFSET));
987    __ Tbz(hclass, JSHClass::IsClassConstructorOrPrototypeBit::START_BIT, &notClass);
988    __ Tbnz(hclass, JSHClass::ConstructorBit::START_BIT, &slowCall);
989    __ Bind(&notClass);
990    Register compiledCodeFlag(X9, W);
991    __ Ldrh(compiledCodeFlag, MemoryOperand(boundTarget, JSFunctionBase::BIT_FIELD_OFFSET));
992    __ Tbz(compiledCodeFlag, JSFunctionBase::IsCompiledCodeBit::START_BIT, &slowCall);
993    __ Bind(&aotCall);
994    {
995        // output: glue:x0 argc:x1 calltarget:x2 argv:x3 this:x4 newtarget:x5
996        __ Mov(Register(X1), Register(X19));
997        __ Mov(Register(X2), boundTarget);
998        __ Add(X3, fp, Immediate(5 * FRAME_SLOT_SIZE)); // 5: skip argc and argv func new this
999        __ Mov(Register(X5), Register(X6));
1000        Register boundCallInternalId(X9);
1001        Register baseAddress(X8);
1002        Register codeAddress(X10);
1003        __ Mov(baseAddress, Immediate(JSThread::GlueData::GetCOStubEntriesOffset(false)));
1004        __ Mov(boundCallInternalId, Immediate(CommonStubCSigns::JsBoundCallInternal));
1005        __ Add(codeAddress, X0, baseAddress);
1006        __ Ldr(codeAddress, MemoryOperand(codeAddress, boundCallInternalId, UXTW, FRAME_SLOT_SIZE_LOG2));
1007        __ Blr(codeAddress);
1008        __ B(&popArgs);
1009    }
1010    __ Bind(&slowCall);
1011    {
1012        __ CallAssemblerStub(stubId, false);
1013        __ B(&popArgs);
1014    }
1015
1016    __ Bind(&popArgs);
1017    PopJSFunctionArgs(assembler, Register(X19), Register(X19));
1018    PopOptimizedArgsConfigFrame(assembler);
1019    __ Ret();
1020}
1021
1022// * uint64_t JSProxyCallInternalWithArgV(uintptr_t glue, JSTaggedType calltarget)
1023// * c++ calling convention call js function
1024// * Arguments:
1025//        %x0 - glue
1026//        %x1 - calltarget
1027
1028void OptimizedCall::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler)
1029{
1030    __ BindAssemblerStub(RTSTUB_ID(JSProxyCallInternalWithArgV));
1031    Register jsfunc(X1);
1032    Register sp(SP);
1033    __ Str(jsfunc, MemoryOperand(sp, DOUBLE_SLOT_SIZE));
1034    JSCallInternal(assembler, jsfunc);
1035}
1036
1037// * uint64_t CallRuntimeWithArgv(uintptr_t glue, uint64_t runtime_id, uint64_t argc, uintptr_t argv)
1038// * cc calling convention call runtime_id's runtion function(c-abi)
1039// * Arguments:
1040//         %x0 - glue
1041//         %x1 - runtime_id
1042//         %x2 - argc
1043//         %x3 - argv
1044//
1045// * Optimized-leaved-frame-with-argv layout as the following:
1046//         +--------------------------+
1047//         |       argv[]             |
1048//         +--------------------------+-------------
1049//         |       argc               |            ^
1050//         |--------------------------|            |
1051//         |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1052//  sp --> |--------------------------|            |
1053//         |       returnAddr         |            |
1054//         |--------------------------|            |
1055//         |       callsiteFp         |            |
1056//         |--------------------------|            |
1057//         |       frameType          |            v
1058//         +--------------------------+-------------
1059
1060void OptimizedCall::CallRuntimeWithArgv(ExtendedAssembler *assembler)
1061{
1062    __ BindAssemblerStub(RTSTUB_ID(CallRuntimeWithArgv));
1063    Register glue(X0);
1064    Register runtimeId(X1);
1065    Register argc(X2);
1066    Register argv(X3);
1067    Register sp(SP);
1068    // 2 : 2 means pair
1069    __ Stp(argc, argv, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
1070    __ Stp(Register(X30), runtimeId, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); // 2 : 2 means pair
1071    Register fp(X29);
1072    // construct leave frame
1073    Register frameType(X9);
1074    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::LEAVE_FRAME_WITH_ARGV)));
1075    __ Stp(frameType, Register(X29), MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); // 2 : 2 means pair
1076    __ Add(Register(FP), sp, Immediate(FRAME_SLOT_SIZE));
1077    __ Str(fp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
1078
1079     // load runtime trampoline address
1080    Register tmp(X9);
1081    Register rtfunc(X9);
1082    // 3 : 3 means 2 << 3 = 8
1083    __ Add(tmp, glue, Operand(runtimeId, LSL, 3));
1084    __ Ldr(rtfunc, MemoryOperand(tmp, JSThread::GlueData::GetRTStubEntriesOffset(false)));
1085    __ Mov(X1, argc);
1086    __ Mov(X2, argv);
1087    __ Blr(rtfunc);
1088    __ Ldp(Register(Zero), Register(X29), MemoryOperand(sp, ExtendedAssembler::PAIR_SLOT_SIZE, POSTINDEX));
1089    __ Ldp(Register(X30), Register(Zero), MemoryOperand(sp, ExtendedAssembler::PAIR_SLOT_SIZE, POSTINDEX));
1090    __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE)); // 2 : 2 means pair
1091    __ Ret();
1092}
1093
1094void OptimizedCall::PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc,
1095                                        Register thisObj, Register newTarget, Register currentSp)
1096{
1097    __ Str(thisObj, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
1098    __ Str(newTarget, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
1099    __ Str(jsfunc, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
1100}
1101
1102void OptimizedCall::PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs)
1103{
1104    Register sp(SP);
1105    Register fp(X6);
1106    Label aligned;
1107    const int64_t argoffsetSlot = static_cast<int64_t>(CommonArgIdx::FUNC) - 1;
1108    if (expectedNumArgs != actualNumArgs) {
1109        TempRegister1Scope scop1(assembler);
1110        Register tmp = __ TempRegister1();
1111        __ Cmp(expectedNumArgs, actualNumArgs);
1112        __ CMov(tmp, expectedNumArgs, actualNumArgs, Condition::HI);
1113        __ Add(sp, sp, Operand(tmp, UXTW, FRAME_SLOT_SIZE_LOG2));
1114    } else {
1115        __ Add(sp, sp, Operand(expectedNumArgs, UXTW, FRAME_SLOT_SIZE_LOG2));
1116    }
1117    __ Add(sp, sp, Immediate(argoffsetSlot * FRAME_SLOT_SIZE));
1118    __ Mov(fp, sp);
1119    __ Tst(fp, LogicalImmediate::Create(0xf, RegXSize));  // 0xf: 0x1111
1120    __ B(Condition::EQ, &aligned);
1121    __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE));
1122    __ Bind(&aligned);
1123}
1124
1125void OptimizedCall::PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp)
1126{
1127    Register fp(X29);
1128    Register sp(SP);
1129    TempRegister2Scope temp2Scope(assembler);
1130    __ PushFpAndLr();
1131    Register frameType = __ TempRegister2();
1132    // construct frame
1133    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_ENTRY_FRAME)));
1134    // 2 : 2 means pairs
1135    __ Stp(prevFp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
1136    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
1137    __ CalleeSave();
1138}
1139
1140void OptimizedCall::PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue)
1141{
1142    Register fp(X29);
1143    Register sp(SP);
1144    Register prevFp(X1);
1145    __ CalleeRestore();
1146
1147    // 2: prevFp and frameType
1148    __ Ldp(prevFp, Register(Zero), MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX));
1149    // restore return address
1150    __ RestoreFpAndLr();
1151    __ Str(prevFp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
1152}
1153
1154void OptimizedCall::PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler)
1155{
1156    Register sp(SP);
1157    TempRegister2Scope temp2Scope(assembler);
1158    Register frameType = __ TempRegister2();
1159    __ PushFpAndLr();
1160    // construct frame
1161    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)));
1162    // 2 : 2 means pairs. X19 means calleesave and 16bytes align
1163    __ Stp(Register(X19), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
1164    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
1165}
1166
1167void OptimizedCall::PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler)
1168{
1169    TempRegister2Scope temp2Scope(assembler);
1170    Register sp(SP);
1171    Register frameType = __ TempRegister2();
1172    // 2 : 2 means pop call site sp and type
1173    __ Ldp(Register(X19), frameType, MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX));
1174    __ RestoreFpAndLr();
1175}
1176
1177// * uint64_t PushOptimizedUnfoldArgVFrame(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
1178//                                         JSTaggedType new, JSTaggedType this, JSTaggedType argV[])
1179// * cc calling convention call js function()
1180// * arguments:
1181//              %x0 - glue
1182//              %x1 - argc
1183//              %x2 - call-target
1184//              %x3 - new-target
1185//              %x4 - this
1186//              %x5 - argv
1187//
1188// * OptimizedUnfoldArgVFrame layout description as the following:
1189//      sp ----> |--------------------------| ---------------
1190//               |       returnAddr         |               ^
1191//  currentFp--> |--------------------------|               |
1192//               |       prevFp             |               |
1193//               |--------------------------|   OptimizedUnfoldArgVFrame
1194//               |       frameType          |               |
1195//               |--------------------------|               |
1196//               |       currentFp          |               v
1197//               +--------------------------+ ---------------
1198
1199void OptimizedCall::PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp)
1200{
1201    Register sp(SP);
1202    TempRegister2Scope temp2Scope(assembler);
1203    Register frameType = __ TempRegister2();
1204    __ PushFpAndLr();
1205    // construct frame
1206    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME)));
1207    // 2 : 2 means pairs
1208    __ Stp(callSiteSp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
1209    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
1210}
1211
1212void OptimizedCall::PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler)
1213{
1214    Register sp(SP);
1215    // 2 : 2 means pop call site sp and type
1216    __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
1217    __ RestoreFpAndLr();
1218}
1219
1220// * uint64_t JSCallWithArgV(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
1221//                          JSTaggedType new, JSTaggedType this, argV)
1222// * cc calling convention call js function()
1223// * arguments:
1224//              %x0 - glue
1225//              %x1 - argc
1226//              %x2 - call-target
1227//              %x3 - new-target
1228//              %x4 - this
1229//              %x5 - argV[]
1230//
1231// * OptimizedJSFunctionFrame layout description as the following:
1232//               +--------------------------+
1233//               |       argn               |
1234//               |--------------------------|
1235//               |       argn - 1           |
1236//               |--------------------------|
1237//               |       .....              |
1238//               |--------------------------|
1239//               |       arg2               |
1240//               |--------------------------|
1241//               |       arg1               |
1242//      sp ----> |--------------------------| ---------------
1243//               |       returnAddr         |               ^
1244//               |--------------------------|               |
1245//               |       callsiteFp         |               |
1246//               |--------------------------|  OptimizedJSFunctionFrame
1247//               |       frameType          |               |
1248//               |--------------------------|               |
1249//               |       call-target        |               v
1250//               +--------------------------+ ---------------
1251
1252void OptimizedCall::GenJSCallWithArgV(ExtendedAssembler *assembler, int id)
1253{
1254    Register sp(SP);
1255    Register glue(X0);
1256    Register actualNumArgs(X1);
1257    Register jsfunc(X2);
1258    Register newTarget(X3);
1259    Register thisObj(X4);
1260    Register argV(X5);
1261    Register currentSp = __ AvailableRegister1();
1262    Register callsiteSp = __ AvailableRegister2();
1263    Label pushCallThis;
1264
1265    __ Mov(callsiteSp, sp);
1266    PushOptimizedUnfoldArgVFrame(assembler, callsiteSp);
1267    Register argC(X7);
1268    __ Add(actualNumArgs, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
1269    __ Mov(argC, actualNumArgs);
1270    IncreaseStackForArguments(assembler, argC, currentSp, static_cast<int64_t>(CommonArgIdx::ACTUAL_ARGV));
1271    {
1272        TempRegister1Scope scope1(assembler);
1273        TempRegister2Scope scope2(assembler);
1274        Register tmp = __ TempRegister1();
1275        Register op = __ TempRegister2();
1276        __ Sub(tmp, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
1277        PushArgsWithArgv(assembler, glue, tmp, argV, op, currentSp, &pushCallThis, nullptr);
1278    }
1279    __ Bind(&pushCallThis);
1280    PushMandatoryJSArgs(assembler, jsfunc, thisObj, newTarget, currentSp);
1281    {
1282        TempRegister1Scope scope1(assembler);
1283        Register tmp = __ TempRegister1();
1284        __ Mov(tmp, currentSp);
1285        __ Str(tmp, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
1286        __ Str(actualNumArgs, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
1287    }
1288    __ CallAssemblerStub(id, false);
1289    __ Ldr(actualNumArgs, MemoryOperand(sp, 0));
1290    PopJSFunctionArgs(assembler, actualNumArgs, actualNumArgs);
1291    PopOptimizedUnfoldArgVFrame(assembler);
1292    __ Ret();
1293}
1294
1295// * uint64_t JSCallWithArgVAndPushArgv(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
1296//                          JSTaggedType new, JSTaggedType this, argV)
1297// * cc calling convention call js function()
1298// * arguments:
1299//              %x0 - glue
1300//              %x1 - argc
1301//              %x2 - call-target
1302//              %x3 - new-target
1303//              %x4  - this
1304//              %x5  - argv
1305void OptimizedCall::JSCallWithArgVAndPushArgv(ExtendedAssembler *assembler)
1306{
1307    __ BindAssemblerStub(RTSTUB_ID(JSCallWithArgVAndPushArgv));
1308    GenJSCallWithArgV(assembler, RTSTUB_ID(OptimizedCallAndPushArgv));
1309}
1310
1311void OptimizedCall::JSCallWithArgV(ExtendedAssembler *assembler)
1312{
1313    __ BindAssemblerStub(RTSTUB_ID(JSCallWithArgV));
1314    GenJSCallWithArgV(assembler, RTSTUB_ID(CallOptimized));
1315}
1316
1317void OptimizedCall::SuperCallWithArgV(ExtendedAssembler *assembler)
1318{
1319    __ BindAssemblerStub(RTSTUB_ID(SuperCallWithArgV));
1320    GenJSCallWithArgV(assembler, RTSTUB_ID(JSCallNew));
1321}
1322
1323void OptimizedCall::CallOptimized(ExtendedAssembler *assembler)
1324{
1325    __ BindAssemblerStub(RTSTUB_ID(CallOptimized));
1326    Register sp(SP);
1327    Register jsfunc(X7);
1328    Register method(X6);
1329    Register codeAddr(X5);
1330    auto funcSlotOffset = kungfu::ArgumentAccessor::GetExtraArgsNum();
1331    __ Ldr(jsfunc, MemoryOperand(sp, funcSlotOffset * FRAME_SLOT_SIZE));
1332    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
1333    __ Ldr(codeAddr, MemoryOperand(jsfunc, JSFunction::CODE_ENTRY_OFFSET));
1334    __ Br(codeAddr);
1335}
1336
1337void OptimizedCall::DeoptEnterAsmInterp(ExtendedAssembler *assembler)
1338{
1339    // rdi
1340    Register glueRegister = __ GlueRegister();
1341    Register context(X2);
1342    Register opRegister(X9);
1343    Register outputCount(X10);
1344    Register frameStateBase(X11);
1345    Register currentSlotRegister(X12);
1346    Register sp(SP);
1347    Register depth(X20);
1348    Register tmpReg(X21);
1349    Label loopBegin;
1350    Label stackOverflow;
1351    Label pushArgv;
1352
1353    __ PushFpAndLr();
1354
1355    __ Ldr(depth, MemoryOperand(context, AsmStackContext::GetInlineDepthOffset(false)));
1356    __ Add(context, context, Immediate(AsmStackContext::GetSize(false)));
1357    __ Mov(Register(X23), Immediate(0));
1358    // update fp
1359    __ Mov(currentSlotRegister, sp);
1360    __ Bind(&loopBegin);
1361    __ Ldr(outputCount, MemoryOperand(context, 0));
1362    __ Add(frameStateBase, context, Immediate(FRAME_SLOT_SIZE));
1363    __ Cmp(Register(X23), Immediate(0));
1364    __ B(Condition::EQ, &pushArgv);
1365    __ Mov(tmpReg, currentSlotRegister);
1366    __ Add(tmpReg, tmpReg, Immediate(AsmInterpretedFrame::GetSize(false)));
1367    __ Add(Register(X9), frameStateBase, Immediate(AsmInterpretedFrame::GetBaseOffset(false)));
1368    __ Str(tmpReg, MemoryOperand(Register(X9), InterpretedFrameBase::GetPrevOffset(false)));
1369    __ Align16(currentSlotRegister);
1370
1371    __ Bind(&pushArgv);
1372    __ Mov(tmpReg, outputCount);
1373    __ Str(currentSlotRegister, MemoryOperand(frameStateBase, AsmInterpretedFrame::GetFpOffset(false)));
1374    PushArgsWithArgv(assembler, glueRegister, outputCount, frameStateBase, opRegister,
1375                     currentSlotRegister, nullptr, &stackOverflow);
1376    __ Add(context, context, Immediate(FRAME_SLOT_SIZE)); // skip outputCount
1377    __ Add(context, context, Operand(tmpReg, UXTW, FRAME_SLOT_SIZE_LOG2)); // skip args
1378    __ Add(Register(X23), Register(X23), Immediate(1));
1379    __ Cmp(depth, Register(X23));
1380    __ B(Condition::GE, &loopBegin);
1381
1382    Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
1383    Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD);
1384    {
1385        // X19, fp, x20, x21,      x22,     x23,  x24
1386        // glue sp   pc  constpool  profile  acc   hotness
1387        __ Ldr(callTargetRegister, MemoryOperand(frameStateBase, AsmInterpretedFrame::GetFunctionOffset(false)));
1388        __ Ldr(Register(X20), MemoryOperand(frameStateBase, AsmInterpretedFrame::GetPcOffset(false)));
1389        __ Ldr(Register(X23), MemoryOperand(frameStateBase, AsmInterpretedFrame::GetAccOffset(false)));
1390        __ Ldr(methodRegister, MemoryOperand(callTargetRegister, JSFunctionBase::METHOD_OFFSET));
1391
1392        __ Add(opRegister, currentSlotRegister, Immediate(AsmInterpretedFrame::GetSize(false)));
1393
1394        __ Align16(currentSlotRegister);
1395        __ Mov(Register(SP), currentSlotRegister);
1396        AsmInterpreterCall::DispatchCall(assembler, Register(X20), opRegister, Register(X23));
1397    }
1398    __ Bind(&stackOverflow);
1399    {
1400        Register temp(X1);
1401        AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(
1402            assembler, glueRegister, sp, temp);
1403    }
1404}
1405
1406void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
1407{
1408    __ BindAssemblerStub(RTSTUB_ID(DeoptHandlerAsm));
1409    __ PushFpAndLr();
1410    Register sp(SP);
1411    Register fp(FP);
1412    Register frameType(X3);
1413    Register glueReg(X0);
1414
1415    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::ASM_BRIDGE_FRAME)));
1416    __ Stp(glueReg, frameType, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
1417    __ Add(fp, sp, Immediate(DOUBLE_SLOT_SIZE));
1418    __ CalleeSave();
1419
1420    Register deoptType(X1);
1421    Register depth(X2);
1422    Register argC(X3);
1423    Register runtimeId(X4);
1424    __ Stp(deoptType, depth, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
1425    __ Mov(argC, Immediate(2)); // 2: argc
1426    __ Mov(runtimeId, Immediate(RTSTUB_ID(DeoptHandler)));
1427    __ Stp(runtimeId, argC, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
1428    __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
1429    __ Add(sp, sp, Immediate(2 * DOUBLE_SLOT_SIZE)); // 2: skip runtimeId, argc, depth, shiftLen
1430
1431    __ CalleeRestore();
1432    Register context(X2);
1433    __ Mov(context, Register(X0));
1434    __ Ldr(glueReg, MemoryOperand(sp, 0));
1435
1436    Register ret(X0);
1437    Label stackOverflow;
1438    __ Cmp(ret, Immediate(JSTaggedValue::VALUE_EXCEPTION));
1439    __ B(Condition::EQ, &stackOverflow);
1440
1441    Label target;
1442    Register temp(X1);
1443    __ Ldr(fp, MemoryOperand(context, AsmStackContext::GetCallerFpOffset(false)));
1444    __ Ldr(temp, MemoryOperand(context, AsmStackContext::GetCallFrameTopOffset(false)));
1445    __ Mov(sp, temp);
1446    __ Ldr(Register(X30), MemoryOperand(context, AsmStackContext::GetReturnAddressOffset(false)));
1447
1448    PushAsmInterpBridgeFrame(assembler);
1449    __ Bl(&target);
1450    PopAsmInterpBridgeFrame(assembler);
1451    __ Ret();
1452    __ Bind(&target);
1453    DeoptEnterAsmInterp(assembler);
1454
1455    __ Bind(&stackOverflow);
1456    {
1457        __ Mov(runtimeId, Immediate(RTSTUB_ID(ThrowStackOverflowException)));
1458        // 2 : 2 means pair
1459        __ Stp(runtimeId, Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
1460        __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
1461        __ Add(sp, sp, Immediate(2 * DOUBLE_SLOT_SIZE)); // 2: skip runtimeId&argc glue&type
1462        __ RestoreFpAndLr();
1463        __ Ret();
1464    }
1465}
1466#undef __
1467}  // panda::ecmascript::aarch64
1468