14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/trampoline/aarch64/common_call.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/assembler.h"
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/argument_accessor.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/rt_call_signature.h"
214514f5e3Sopenharmony_ci#include "ecmascript/deoptimizer/deoptimizer.h"
224514f5e3Sopenharmony_ci#include "ecmascript/ecma_runtime_call_info.h"
234514f5e3Sopenharmony_ci#include "ecmascript/frames.h"
244514f5e3Sopenharmony_ci#include "ecmascript/js_function.h"
254514f5e3Sopenharmony_ci#include "ecmascript/method.h"
264514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h"
274514f5e3Sopenharmony_ci#include "ecmascript/message_string.h"
284514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h"
294514f5e3Sopenharmony_ci
304514f5e3Sopenharmony_cinamespace panda::ecmascript::aarch64 {
314514f5e3Sopenharmony_ciusing Label = panda::ecmascript::Label;
324514f5e3Sopenharmony_ci#define __ assembler->
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ci// * uint64_t CallRuntime(uintptr_t glue, uint64_t runtime_id, uint64_t argc, uintptr_t arg0, ...)
354514f5e3Sopenharmony_ci// * webkit_jscc calling convention call runtime_id's runtime function(c-abi)
364514f5e3Sopenharmony_ci// * Arguments:
374514f5e3Sopenharmony_ci//         %x0 - glue
384514f5e3Sopenharmony_ci//
394514f5e3Sopenharmony_ci// * Optimized-leaved-frame layout as the following:
404514f5e3Sopenharmony_ci//         +--------------------------+
414514f5e3Sopenharmony_ci//         |       argv[N-1]          |
424514f5e3Sopenharmony_ci//         |--------------------------|
434514f5e3Sopenharmony_ci//         |       . . . . .          |
444514f5e3Sopenharmony_ci//         |--------------------------|
454514f5e3Sopenharmony_ci//         |       argv[0]            |
464514f5e3Sopenharmony_ci//         +--------------------------+-------------
474514f5e3Sopenharmony_ci//         |       argc               |            ^
484514f5e3Sopenharmony_ci//         |--------------------------|            |
494514f5e3Sopenharmony_ci//         |       RuntimeId          |            |
504514f5e3Sopenharmony_ci//  sp --> |--------------------------|   OptimizedLeaveFrame
514514f5e3Sopenharmony_ci//         |       ret-addr           |            |
524514f5e3Sopenharmony_ci//         |--------------------------|            |
534514f5e3Sopenharmony_ci//         |       prevFp             |            |
544514f5e3Sopenharmony_ci//         |--------------------------|            |
554514f5e3Sopenharmony_ci//         |       frameType          |            v
564514f5e3Sopenharmony_ci//         +--------------------------+-------------
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_civoid OptimizedCall::CallRuntime(ExtendedAssembler *assembler)
594514f5e3Sopenharmony_ci{
604514f5e3Sopenharmony_ci    Register glue(X0);
614514f5e3Sopenharmony_ci    Register fp(FP);
624514f5e3Sopenharmony_ci    Register tmp(X19);
634514f5e3Sopenharmony_ci    Register sp(SP);
644514f5e3Sopenharmony_ci    Register argC(X1);
654514f5e3Sopenharmony_ci    Register argV(X2);
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallRuntime));
684514f5e3Sopenharmony_ci    __ PushFpAndLr();
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci    Register frameType(X2);
714514f5e3Sopenharmony_ci    // construct Leave Frame and callee save
724514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::LEAVE_FRAME)));
734514f5e3Sopenharmony_ci    // 2 : 2 means pairs
744514f5e3Sopenharmony_ci    __ Stp(tmp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
754514f5e3Sopenharmony_ci    __ Add(fp, sp, Immediate(2 * FRAME_SLOT_SIZE));  // 2 : 2 means pairs
764514f5e3Sopenharmony_ci    __ Str(fp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci    // load runtime trampoline address
794514f5e3Sopenharmony_ci    Register rtfunc(X19);
804514f5e3Sopenharmony_ci    __ Ldr(tmp, MemoryOperand(fp, GetStackArgOffSetToFp(0)));  // 0: the first arg id
814514f5e3Sopenharmony_ci    // 3 : 3 means 2 << 3 = 8
824514f5e3Sopenharmony_ci    __ Add(tmp, glue, Operand(tmp, LSL, 3));
834514f5e3Sopenharmony_ci    __ Ldr(rtfunc, MemoryOperand(tmp, JSThread::GlueData::GetRTStubEntriesOffset(false)));
844514f5e3Sopenharmony_ci    __ Ldr(argC, MemoryOperand(fp, GetStackArgOffSetToFp(1)));  // 1: the second arg id
854514f5e3Sopenharmony_ci    __ Add(argV, fp, Immediate(GetStackArgOffSetToFp(2)));  // 2: the third arg id
864514f5e3Sopenharmony_ci    __ Blr(rtfunc);
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_ci    // callee restore
894514f5e3Sopenharmony_ci    // 0 : 0 restore size
904514f5e3Sopenharmony_ci    __ Ldr(tmp, MemoryOperand(sp, 0));
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ci    // descontruct frame
934514f5e3Sopenharmony_ci    // 2 :2 means stack frame slot size
944514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
954514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
964514f5e3Sopenharmony_ci    __ Ret();
974514f5e3Sopenharmony_ci}
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_civoid OptimizedCall::IncreaseStackForArguments(ExtendedAssembler *assembler, Register argc, Register currentSp,
1004514f5e3Sopenharmony_ci                                              int64_t numExtraArgs)
1014514f5e3Sopenharmony_ci{
1024514f5e3Sopenharmony_ci    Register sp(SP);
1034514f5e3Sopenharmony_ci    __ Mov(currentSp, sp);
1044514f5e3Sopenharmony_ci    if (numExtraArgs > 0) {
1054514f5e3Sopenharmony_ci        // add extra aguments, numArgs
1064514f5e3Sopenharmony_ci        __ Add(argc, argc, Immediate(numExtraArgs));
1074514f5e3Sopenharmony_ci    }
1084514f5e3Sopenharmony_ci    __ Sub(currentSp, currentSp, Operand(argc, UXTW, FRAME_SLOT_SIZE_LOG2));
1094514f5e3Sopenharmony_ci    Label aligned;
1104514f5e3Sopenharmony_ci    __ Tst(currentSp, LogicalImmediate::Create(0xf, RegXSize));  // 0xf: 0x1111
1114514f5e3Sopenharmony_ci    __ B(Condition::EQ, &aligned);
1124514f5e3Sopenharmony_ci    __ Sub(currentSp, currentSp, Immediate(FRAME_SLOT_SIZE));
1134514f5e3Sopenharmony_ci    __ Bind(&aligned);
1144514f5e3Sopenharmony_ci    __ Mov(sp, currentSp);
1154514f5e3Sopenharmony_ci    __ Add(currentSp, currentSp, Operand(argc, UXTW, FRAME_SLOT_SIZE_LOG2));
1164514f5e3Sopenharmony_ci}
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ci// * uint64_t JSFunctionEntry(uintptr_t glue, uint32_t actualNumArgs, const JSTaggedType argV[], uintptr_t prevFp,
1194514f5e3Sopenharmony_ci//                            size_t callType)
1204514f5e3Sopenharmony_ci// * Arguments:
1214514f5e3Sopenharmony_ci//        %x0 - glue
1224514f5e3Sopenharmony_ci//        %x1 - actualNumArgs
1234514f5e3Sopenharmony_ci//        %x2 - argV
1244514f5e3Sopenharmony_ci//        %x3 - prevFp
1254514f5e3Sopenharmony_ci//        %x4 - needPushArgv
1264514f5e3Sopenharmony_ci//
1274514f5e3Sopenharmony_ci// * The JSFunctionEntry Frame's structure is illustrated as the following:
1284514f5e3Sopenharmony_ci//          +--------------------------+
1294514f5e3Sopenharmony_ci//          |      . . . . . .         |
1304514f5e3Sopenharmony_ci//  sp ---> +--------------------------+ -----------------
1314514f5e3Sopenharmony_ci//          |        prevFP            |                 ^
1324514f5e3Sopenharmony_ci//          |--------------------------|                 |
1334514f5e3Sopenharmony_ci//          |       frameType          |      JSFunctionEntryFrame
1344514f5e3Sopenharmony_ci//          |--------------------------|                 |
1354514f5e3Sopenharmony_ci//          |    preLeaveFrameFp       |                 v
1364514f5e3Sopenharmony_ci//          +--------------------------+ -----------------
1374514f5e3Sopenharmony_ci
1384514f5e3Sopenharmony_civoid OptimizedCall::JSFunctionEntry(ExtendedAssembler *assembler)
1394514f5e3Sopenharmony_ci{
1404514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(JSFunctionEntry));
1414514f5e3Sopenharmony_ci    Register glueReg(X0);
1424514f5e3Sopenharmony_ci    Register argV(X2);
1434514f5e3Sopenharmony_ci    Register prevFpReg(X3);
1444514f5e3Sopenharmony_ci    Register needPushArgv(X4);
1454514f5e3Sopenharmony_ci    Register sp(SP);
1464514f5e3Sopenharmony_ci    Register tmpArgV(X7);
1474514f5e3Sopenharmony_ci    Label lJSCallWithArgVAndPushArgv;
1484514f5e3Sopenharmony_ci    Label lPopFrame;
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ci    PushJSFunctionEntryFrame (assembler, prevFpReg);
1514514f5e3Sopenharmony_ci    __ Mov(Register(X6), needPushArgv);
1524514f5e3Sopenharmony_ci    __ Mov(tmpArgV, argV);
1534514f5e3Sopenharmony_ci    __ Mov(Register(X20), glueReg);
1544514f5e3Sopenharmony_ci    __ Ldr(Register(X2), MemoryOperand(tmpArgV, 0));
1554514f5e3Sopenharmony_ci    __ Ldr(Register(X3), MemoryOperand(tmpArgV, FRAME_SLOT_SIZE));
1564514f5e3Sopenharmony_ci    __ Ldr(Register(X4), MemoryOperand(tmpArgV, DOUBLE_SLOT_SIZE));
1574514f5e3Sopenharmony_ci    __ Add(tmpArgV, tmpArgV, Immediate(TRIPLE_SLOT_SIZE));
1584514f5e3Sopenharmony_ci    __ Mov(Register(X5), tmpArgV);
1594514f5e3Sopenharmony_ci    __ Cmp(Register(X6), Immediate(1));
1604514f5e3Sopenharmony_ci    __ B(Condition::EQ, &lJSCallWithArgVAndPushArgv);
1614514f5e3Sopenharmony_ci    __ CallAssemblerStub(RTSTUB_ID(JSCallWithArgV), false);
1624514f5e3Sopenharmony_ci    __ B(&lPopFrame);
1634514f5e3Sopenharmony_ci
1644514f5e3Sopenharmony_ci    __ Bind(&lJSCallWithArgVAndPushArgv);
1654514f5e3Sopenharmony_ci    __ CallAssemblerStub(RTSTUB_ID(JSCallWithArgVAndPushArgv), false);
1664514f5e3Sopenharmony_ci    __ Bind(&lPopFrame);
1674514f5e3Sopenharmony_ci    __ Mov(Register(X2), Register(X20));
1684514f5e3Sopenharmony_ci    PopJSFunctionEntryFrame(assembler, Register(X2));
1694514f5e3Sopenharmony_ci    __ Ret();
1704514f5e3Sopenharmony_ci}
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci// * uint64_t OptimizedCallAndPushArgv(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, JSTaggedType new,
1734514f5e3Sopenharmony_ci//                   JSTaggedType this, arg[0], arg[1], arg[2], ..., arg[N-1])
1744514f5e3Sopenharmony_ci// * webkit_jscc calling convention call js function()
1754514f5e3Sopenharmony_ci//
1764514f5e3Sopenharmony_ci// * OptimizedJSFunctionFrame layout description as the following:
1774514f5e3Sopenharmony_ci//               +--------------------------+
1784514f5e3Sopenharmony_ci//               |        arg[N-1]          |
1794514f5e3Sopenharmony_ci//               +--------------------------+
1804514f5e3Sopenharmony_ci//               |       ...                |
1814514f5e3Sopenharmony_ci//               +--------------------------+
1824514f5e3Sopenharmony_ci//               |       arg[1]             |
1834514f5e3Sopenharmony_ci//               +--------------------------+
1844514f5e3Sopenharmony_ci//               |       arg[0]             |
1854514f5e3Sopenharmony_ci//               +--------------------------+
1864514f5e3Sopenharmony_ci//               |       this               |
1874514f5e3Sopenharmony_ci//               +--------------------------+
1884514f5e3Sopenharmony_ci//               |       new-target         |
1894514f5e3Sopenharmony_ci//               +--------------------------+
1904514f5e3Sopenharmony_ci//               |       call-target        |
1914514f5e3Sopenharmony_ci//               +--------------------------+
1924514f5e3Sopenharmony_ci//               |       argv               |
1934514f5e3Sopenharmony_ci//               +--------------------------+
1944514f5e3Sopenharmony_ci//               |       argc               |
1954514f5e3Sopenharmony_ci//     sp ---->  |--------------------------| ---------------
1964514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
1974514f5e3Sopenharmony_ci//               |--------------------------|               |
1984514f5e3Sopenharmony_ci//               |       callsiteFp         |               |
1994514f5e3Sopenharmony_ci//               |--------------------------|   OptimizedJSFunctionFrame
2004514f5e3Sopenharmony_ci//               |       frameType          |               |
2014514f5e3Sopenharmony_ci//               |--------------------------|               |
2024514f5e3Sopenharmony_ci//               |       call-target        |               v
2034514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
2044514f5e3Sopenharmony_civoid OptimizedCall::OptimizedCallAndPushArgv(ExtendedAssembler *assembler)
2054514f5e3Sopenharmony_ci{
2064514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(OptimizedCallAndPushArgv));
2074514f5e3Sopenharmony_ci    Register sp(SP);
2084514f5e3Sopenharmony_ci    Register jsfunc(X7);
2094514f5e3Sopenharmony_ci    Register method(X6);
2104514f5e3Sopenharmony_ci    Register expectedNumArgs(X1);
2114514f5e3Sopenharmony_ci    Register actualNumArgs(X2);
2124514f5e3Sopenharmony_ci    Register codeAddr(X3);
2134514f5e3Sopenharmony_ci    Register argV(X4);
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_ci    auto funcSlotOffSet = kungfu::ArgumentAccessor::GetExtraArgsNum();
2164514f5e3Sopenharmony_ci    __ Ldr(jsfunc, MemoryOperand(sp, funcSlotOffSet * FRAME_SLOT_SIZE));
2174514f5e3Sopenharmony_ci    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
2184514f5e3Sopenharmony_ci    __ Ldr(codeAddr, MemoryOperand(jsfunc, JSFunction::CODE_ENTRY_OFFSET));
2194514f5e3Sopenharmony_ci    __ Ldr(expectedNumArgs, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
2204514f5e3Sopenharmony_ci    __ Lsr(expectedNumArgs, expectedNumArgs, MethodLiteral::NumArgsBits::START_BIT);
2214514f5e3Sopenharmony_ci    __ And(expectedNumArgs, expectedNumArgs,
2224514f5e3Sopenharmony_ci        LogicalImmediate::Create(
2234514f5e3Sopenharmony_ci            MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize));
2244514f5e3Sopenharmony_ci    __ Add(expectedNumArgs, expectedNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
2254514f5e3Sopenharmony_ci
2264514f5e3Sopenharmony_ci    __ Add(argV, sp, Immediate(funcSlotOffSet * FRAME_SLOT_SIZE));  // skip numArgs and argv
2274514f5e3Sopenharmony_ci    __ Ldr(actualNumArgs, MemoryOperand(sp, 0));
2284514f5e3Sopenharmony_ci
2294514f5e3Sopenharmony_ci    Register glue(X0);
2304514f5e3Sopenharmony_ci    Register currentSp(X5);
2314514f5e3Sopenharmony_ci    Label copyArguments;
2324514f5e3Sopenharmony_ci    Label invokeCompiledJSFunction;
2334514f5e3Sopenharmony_ci
2344514f5e3Sopenharmony_ci    // construct frame
2354514f5e3Sopenharmony_ci    PushOptimizedArgsConfigFrame(assembler);
2364514f5e3Sopenharmony_ci    Register argC(X7);
2374514f5e3Sopenharmony_ci    __ Cmp(expectedNumArgs, actualNumArgs);
2384514f5e3Sopenharmony_ci    __ CMov(argC, expectedNumArgs, actualNumArgs, Condition::HI);
2394514f5e3Sopenharmony_ci    IncreaseStackForArguments(assembler, argC, currentSp, static_cast<int64_t>(CommonArgIdx::ACTUAL_ARGV));
2404514f5e3Sopenharmony_ci    {
2414514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
2424514f5e3Sopenharmony_ci        TempRegister2Scope scope2(assembler);
2434514f5e3Sopenharmony_ci        Register tmp = __ TempRegister1();
2444514f5e3Sopenharmony_ci        Register undefinedValue = __ TempRegister2();
2454514f5e3Sopenharmony_ci        __ Subs(tmp, expectedNumArgs, actualNumArgs);
2464514f5e3Sopenharmony_ci        __ B(Condition::LS, &copyArguments);
2474514f5e3Sopenharmony_ci        PushUndefinedWithArgc(assembler, glue, tmp, undefinedValue, currentSp, nullptr, nullptr);
2484514f5e3Sopenharmony_ci    }
2494514f5e3Sopenharmony_ci    __ Bind(&copyArguments);
2504514f5e3Sopenharmony_ci    __ Cbz(actualNumArgs, &invokeCompiledJSFunction);
2514514f5e3Sopenharmony_ci    {
2524514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
2534514f5e3Sopenharmony_ci        TempRegister2Scope scope2(assembler);
2544514f5e3Sopenharmony_ci        Register argc = __ TempRegister1();
2554514f5e3Sopenharmony_ci        Register argValue = __ TempRegister2();
2564514f5e3Sopenharmony_ci        __ Mov(argc, actualNumArgs);
2574514f5e3Sopenharmony_ci        PushArgsWithArgv(assembler, glue, argc, argV, argValue, currentSp, &invokeCompiledJSFunction, nullptr);
2584514f5e3Sopenharmony_ci    }
2594514f5e3Sopenharmony_ci    __ Bind(&invokeCompiledJSFunction);
2604514f5e3Sopenharmony_ci    {
2614514f5e3Sopenharmony_ci        __ Mov(Register(X19), expectedNumArgs);
2624514f5e3Sopenharmony_ci        __ Str(currentSp, MemoryOperand(sp, FRAME_SLOT_SIZE));
2634514f5e3Sopenharmony_ci        __ Str(actualNumArgs, MemoryOperand(sp, 0)); // argv, argc
2644514f5e3Sopenharmony_ci        __ Blr(codeAddr);
2654514f5e3Sopenharmony_ci    }
2664514f5e3Sopenharmony_ci
2674514f5e3Sopenharmony_ci    // pop argV argC
2684514f5e3Sopenharmony_ci    // 3 : 3 means argC * 8
2694514f5e3Sopenharmony_ci    __ Ldr(actualNumArgs, MemoryOperand(sp, 0));
2704514f5e3Sopenharmony_ci    PopJSFunctionArgs(assembler, Register(X19), actualNumArgs);
2714514f5e3Sopenharmony_ci    // pop prevLeaveFrameFp to restore thread->currentFrame_
2724514f5e3Sopenharmony_ci    PopOptimizedArgsConfigFrame(assembler);
2734514f5e3Sopenharmony_ci    __ Ret();
2744514f5e3Sopenharmony_ci}
2754514f5e3Sopenharmony_ci
2764514f5e3Sopenharmony_civoid OptimizedCall::OptimizedCallAsmInterpreter(ExtendedAssembler *assembler)
2774514f5e3Sopenharmony_ci{
2784514f5e3Sopenharmony_ci    Label target;
2794514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
2804514f5e3Sopenharmony_ci    __ Bl(&target);
2814514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
2824514f5e3Sopenharmony_ci    __ Ret();
2834514f5e3Sopenharmony_ci    __ Bind(&target);
2844514f5e3Sopenharmony_ci    {
2854514f5e3Sopenharmony_ci        AsmInterpreterCall::JSCallCommonEntry(assembler, JSCallMode::CALL_FROM_AOT,
2864514f5e3Sopenharmony_ci                                              FrameTransitionType::OTHER_TO_OTHER);
2874514f5e3Sopenharmony_ci    }
2884514f5e3Sopenharmony_ci}
2894514f5e3Sopenharmony_ci
2904514f5e3Sopenharmony_ci// * uint64_t CallBuiltinTrampoline(uintptr_t glue, uintptr_t codeAddress, uint32_t argc, ...)
2914514f5e3Sopenharmony_ci// * webkit_jscc calling convention call runtime_id's runtime function(c-abi)
2924514f5e3Sopenharmony_ci// * Argument:
2934514f5e3Sopenharmony_ci//           %x0: glue
2944514f5e3Sopenharmony_ci//
2954514f5e3Sopenharmony_ci// * Construct Native Leave Frame Layout:
2964514f5e3Sopenharmony_ci//          +--------------------------+
2974514f5e3Sopenharmony_ci//          |       argv[N-1]          |
2984514f5e3Sopenharmony_ci//          +--------------------------+
2994514f5e3Sopenharmony_ci//          |      . . . . . .         |
3004514f5e3Sopenharmony_ci//          +--------------------------+
3014514f5e3Sopenharmony_ci//          |      argv[3]=a0          |
3024514f5e3Sopenharmony_ci//          +--------------------------+
3034514f5e3Sopenharmony_ci//          |      argv[2]=this        |
3044514f5e3Sopenharmony_ci//          +--------------------------+
3054514f5e3Sopenharmony_ci//          |   argv[1]=new-target     |
3064514f5e3Sopenharmony_ci//          +--------------------------+
3074514f5e3Sopenharmony_ci//          |   argv[0]=call-target    |
3084514f5e3Sopenharmony_ci//          +--------------------------+ -----------------
3094514f5e3Sopenharmony_ci//          |       argc               |                 ^
3104514f5e3Sopenharmony_ci//          |--------------------------|                 |
3114514f5e3Sopenharmony_ci//          |       thread             |                 |
3124514f5e3Sopenharmony_ci//          |--------------------------|                 |
3134514f5e3Sopenharmony_ci//          |       returnAddr         |    OptimizedBuiltinLeaveFrame
3144514f5e3Sopenharmony_ci//  sp ---> |--------------------------|                 |
3154514f5e3Sopenharmony_ci//          |       callsiteFp         |                 |
3164514f5e3Sopenharmony_ci//          |--------------------------|                 |
3174514f5e3Sopenharmony_ci//          |       frameType          |                 v
3184514f5e3Sopenharmony_ci//          +--------------------------+ -----------------
3194514f5e3Sopenharmony_ci
3204514f5e3Sopenharmony_civoid OptimizedCall::CallBuiltinTrampoline(ExtendedAssembler *assembler)
3214514f5e3Sopenharmony_ci{
3224514f5e3Sopenharmony_ci    Register glue(X0);
3234514f5e3Sopenharmony_ci    Register sp(SP);
3244514f5e3Sopenharmony_ci    Register nativeFuncAddr(X4);
3254514f5e3Sopenharmony_ci    Register temp(X1);
3264514f5e3Sopenharmony_ci
3274514f5e3Sopenharmony_ci    // remove argv
3284514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(sp, 0));
3294514f5e3Sopenharmony_ci    __ Stp(glue, temp, MemoryOperand(sp, 0));   // argc, glue
3304514f5e3Sopenharmony_ci    // returnAddr, callsiteFp
3314514f5e3Sopenharmony_ci    __ Stp(Register(X29), Register(X30), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
3324514f5e3Sopenharmony_ci    __ Mov(temp, sp);
3334514f5e3Sopenharmony_ci    __ Str(temp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); // rbp
3344514f5e3Sopenharmony_ci    __ Mov(Register(X29), temp); // rbp
3354514f5e3Sopenharmony_ci    __ Mov(temp, Immediate(static_cast<int32_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME)));
3364514f5e3Sopenharmony_ci    __ Stp(Register(Zero), temp, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); // frameType, argv
3374514f5e3Sopenharmony_ci    __ Add(Register(X0), sp, Immediate(QUADRUPLE_SLOT_SIZE));
3384514f5e3Sopenharmony_ci    __ Blr(nativeFuncAddr);
3394514f5e3Sopenharmony_ci
3404514f5e3Sopenharmony_ci    __ Mov(sp, Register(FP));
3414514f5e3Sopenharmony_ci    __ Ldp(Register(X29), Register(X30), MemoryOperand(sp, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
3424514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(sp, FRAME_SLOT_SIZE)); // argc
3434514f5e3Sopenharmony_ci    __ Stp(temp, Register(Zero), MemoryOperand(sp, 0)); // argv, argc
3444514f5e3Sopenharmony_ci
3454514f5e3Sopenharmony_ci    __ Ret();
3464514f5e3Sopenharmony_ci}
3474514f5e3Sopenharmony_ci
3484514f5e3Sopenharmony_ci// * uint64_t CallBuiltinConstructorStub(uintptr_t glue, uintptr_t codeAddress, uint32_t argc, ...)
3494514f5e3Sopenharmony_ci// * webkit_jscc calling convention call runtime_id's runtime function(c-abi)
3504514f5e3Sopenharmony_ci//
3514514f5e3Sopenharmony_ci// * Construct Native Leave Frame Layout:
3524514f5e3Sopenharmony_ci//          +--------------------------+
3534514f5e3Sopenharmony_ci//          |       argv[N-1]          |
3544514f5e3Sopenharmony_ci//          +--------------------------+
3554514f5e3Sopenharmony_ci//          |      . . . . . .         |
3564514f5e3Sopenharmony_ci//          +--------------------------+
3574514f5e3Sopenharmony_ci//          |      argv[3]=a0          |
3584514f5e3Sopenharmony_ci//          +--------------------------+
3594514f5e3Sopenharmony_ci//          |      argv[2]=this        |
3604514f5e3Sopenharmony_ci//          +--------------------------+
3614514f5e3Sopenharmony_ci//          |   argv[1]=new-target     |
3624514f5e3Sopenharmony_ci//          +--------------------------+
3634514f5e3Sopenharmony_ci//          |   argv[0]=call-target    |
3644514f5e3Sopenharmony_ci//          +--------------------------+ -----------------
3654514f5e3Sopenharmony_ci//          |       argc               |                 ^
3664514f5e3Sopenharmony_ci//          |--------------------------|                 |
3674514f5e3Sopenharmony_ci//          |       thread             |                 |
3684514f5e3Sopenharmony_ci//          |--------------------------|                 |
3694514f5e3Sopenharmony_ci//          |       returnAddr         |    OptimizedBuiltinLeaveFrame
3704514f5e3Sopenharmony_ci//  sp ---> |--------------------------|                 |
3714514f5e3Sopenharmony_ci//          |       callsiteFp         |                 |
3724514f5e3Sopenharmony_ci//          |--------------------------|                 |
3734514f5e3Sopenharmony_ci//          |       frameType          |                 v
3744514f5e3Sopenharmony_ci//          +--------------------------+ -----------------
3754514f5e3Sopenharmony_ci
3764514f5e3Sopenharmony_civoid OptimizedCall::CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv,
3774514f5e3Sopenharmony_ci                                               Register glue, Register temp)
3784514f5e3Sopenharmony_ci{
3794514f5e3Sopenharmony_ci    Register sp(SP);
3804514f5e3Sopenharmony_ci
3814514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(sp, 0));
3824514f5e3Sopenharmony_ci    __ Stp(glue, temp, MemoryOperand(sp, 0));   // argc, glue
3834514f5e3Sopenharmony_ci    // returnAddr, callsiteFp
3844514f5e3Sopenharmony_ci    __ Stp(Register(X29), Register(X30), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
3854514f5e3Sopenharmony_ci    __ Mov(temp, sp);
3864514f5e3Sopenharmony_ci    __ Mov(Register(X29), temp); // rbp
3874514f5e3Sopenharmony_ci    __ Mov(temp, Immediate(static_cast<int32_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME)));
3884514f5e3Sopenharmony_ci    __ Stp(Register(Zero), temp, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); // frameType, argv
3894514f5e3Sopenharmony_ci    __ Add(argv, sp, Immediate(NONUPLE_SLOT_SIZE));
3904514f5e3Sopenharmony_ci    __ Blr(builtinStub);
3914514f5e3Sopenharmony_ci
3924514f5e3Sopenharmony_ci    __ Mov(sp, Register(FP));
3934514f5e3Sopenharmony_ci    __ Ldp(Register(X29), Register(X30), MemoryOperand(sp, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
3944514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(sp, FRAME_SLOT_SIZE)); // argc
3954514f5e3Sopenharmony_ci    __ Stp(temp, Register(Zero), MemoryOperand(sp, 0)); // argv, argc
3964514f5e3Sopenharmony_ci
3974514f5e3Sopenharmony_ci    __ Ret();
3984514f5e3Sopenharmony_ci}
3994514f5e3Sopenharmony_ci
4004514f5e3Sopenharmony_ci// * uint64_t JSCall(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, JSTaggedType new,
4014514f5e3Sopenharmony_ci//                   JSTaggedType this, arg[0], arg[1], arg[2], ..., arg[N-1])
4024514f5e3Sopenharmony_ci// * webkit_jscc calling convention call js function()
4034514f5e3Sopenharmony_ci//
4044514f5e3Sopenharmony_ci// * OptimizedJSFunctionFrame layout description as the following:
4054514f5e3Sopenharmony_ci//               +--------------------------+
4064514f5e3Sopenharmony_ci//               |        arg[N-1]          |
4074514f5e3Sopenharmony_ci//               +--------------------------+
4084514f5e3Sopenharmony_ci//               |       ...                |
4094514f5e3Sopenharmony_ci//               +--------------------------+
4104514f5e3Sopenharmony_ci//               |       arg[1]             |
4114514f5e3Sopenharmony_ci//               +--------------------------+
4124514f5e3Sopenharmony_ci//               |       arg[0]             |
4134514f5e3Sopenharmony_ci//               +--------------------------+
4144514f5e3Sopenharmony_ci//               |       this               |
4154514f5e3Sopenharmony_ci//               +--------------------------+
4164514f5e3Sopenharmony_ci//               |       new-target         |
4174514f5e3Sopenharmony_ci//               +--------------------------+
4184514f5e3Sopenharmony_ci//               |       call-target        |
4194514f5e3Sopenharmony_ci//               +--------------------------+
4204514f5e3Sopenharmony_ci//               |       argv               |
4214514f5e3Sopenharmony_ci//               |--------------------------|
4224514f5e3Sopenharmony_ci//               |       argc               |
4234514f5e3Sopenharmony_ci//      sp ----> |--------------------------| ---------------
4244514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
4254514f5e3Sopenharmony_ci//               |--------------------------|               |
4264514f5e3Sopenharmony_ci//               |       callsiteFp         |               |
4274514f5e3Sopenharmony_ci//               |--------------------------|   OptimizedJSFunctionFrame
4284514f5e3Sopenharmony_ci//               |       frameType          |               |
4294514f5e3Sopenharmony_ci//               |--------------------------|               |
4304514f5e3Sopenharmony_ci//               |       call-target        |               v
4314514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
4324514f5e3Sopenharmony_ci
4334514f5e3Sopenharmony_civoid OptimizedCall::GenJSCall(ExtendedAssembler *assembler, bool isNew)
4344514f5e3Sopenharmony_ci{
4354514f5e3Sopenharmony_ci    Register jsfunc(X1);
4364514f5e3Sopenharmony_ci    Register sp(SP);
4374514f5e3Sopenharmony_ci    __ Ldr(jsfunc, MemoryOperand(sp, DOUBLE_SLOT_SIZE)); // skip 2: argc, argv
4384514f5e3Sopenharmony_ci    JSCallInternal(assembler, jsfunc, isNew);
4394514f5e3Sopenharmony_ci}
4404514f5e3Sopenharmony_ci
4414514f5e3Sopenharmony_civoid OptimizedCall::JSCallNew(ExtendedAssembler *assembler)
4424514f5e3Sopenharmony_ci{
4434514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(JSCallNew));
4444514f5e3Sopenharmony_ci    GenJSCall(assembler, true);
4454514f5e3Sopenharmony_ci}
4464514f5e3Sopenharmony_ci
4474514f5e3Sopenharmony_civoid OptimizedCall::JSCall(ExtendedAssembler *assembler)
4484514f5e3Sopenharmony_ci{
4494514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(JSCall));
4504514f5e3Sopenharmony_ci    GenJSCall(assembler, false);
4514514f5e3Sopenharmony_ci}
4524514f5e3Sopenharmony_ci
4534514f5e3Sopenharmony_civoid OptimizedCall::JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew)
4544514f5e3Sopenharmony_ci{
4554514f5e3Sopenharmony_ci    Register sp(SP);
4564514f5e3Sopenharmony_ci    Register glue(X0);
4574514f5e3Sopenharmony_ci    Register taggedValue(X2);
4584514f5e3Sopenharmony_ci    Label nonCallable;
4594514f5e3Sopenharmony_ci    Label notJSFunction;
4604514f5e3Sopenharmony_ci    JSCallCheck(assembler, jsfunc, taggedValue, &nonCallable, &notJSFunction);
4614514f5e3Sopenharmony_ci
4624514f5e3Sopenharmony_ci    Register method(X2);
4634514f5e3Sopenharmony_ci    Register callField(X3);
4644514f5e3Sopenharmony_ci    Register actualArgC(X4);
4654514f5e3Sopenharmony_ci    Label callNativeMethod;
4664514f5e3Sopenharmony_ci    Label lCallConstructor;
4674514f5e3Sopenharmony_ci    Label lCallBuiltinStub;
4684514f5e3Sopenharmony_ci    Label lCallNativeCpp;
4694514f5e3Sopenharmony_ci    Label lNotClass;
4704514f5e3Sopenharmony_ci
4714514f5e3Sopenharmony_ci    __ Ldr(Register(X5), MemoryOperand(jsfunc, 0));
4724514f5e3Sopenharmony_ci    __ Ldr(Register(X5), MemoryOperand(Register(X5), JSHClass::BIT_FIELD_OFFSET));
4734514f5e3Sopenharmony_ci    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
4744514f5e3Sopenharmony_ci    __ Ldr(actualArgC, MemoryOperand(sp, 0));
4754514f5e3Sopenharmony_ci    __ Ldr(callField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
4764514f5e3Sopenharmony_ci    __ Tbnz(callField, MethodLiteral::IsNativeBit::START_BIT, &callNativeMethod);
4774514f5e3Sopenharmony_ci    if (!isNew) {
4784514f5e3Sopenharmony_ci        __ Tbz(Register(X5), JSHClass::IsClassConstructorOrPrototypeBit::START_BIT, &lNotClass);
4794514f5e3Sopenharmony_ci        __ Tbnz(Register(X5), JSHClass::ConstructorBit::START_BIT, &lCallConstructor);
4804514f5e3Sopenharmony_ci    }
4814514f5e3Sopenharmony_ci    __ Bind(&lNotClass);
4824514f5e3Sopenharmony_ci    {
4834514f5e3Sopenharmony_ci        Register argV(X5);
4844514f5e3Sopenharmony_ci        // skip argc and argv
4854514f5e3Sopenharmony_ci        __ Add(argV, sp, Immediate(kungfu::ArgumentAccessor::GetExtraArgsNum() * FRAME_SLOT_SIZE));
4864514f5e3Sopenharmony_ci        // asm interpreter argV = argv + 24
4874514f5e3Sopenharmony_ci        __ Add(argV, argV, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE));
4884514f5e3Sopenharmony_ci        __ Sub(actualArgC, actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()));
4894514f5e3Sopenharmony_ci        OptimizedCallAsmInterpreter(assembler);
4904514f5e3Sopenharmony_ci    }
4914514f5e3Sopenharmony_ci
4924514f5e3Sopenharmony_ci    __ Bind(&callNativeMethod);
4934514f5e3Sopenharmony_ci    {
4944514f5e3Sopenharmony_ci        Register nativeFuncAddr(X4);
4954514f5e3Sopenharmony_ci        if (!isNew) {
4964514f5e3Sopenharmony_ci            __ Tbz(callField, MethodLiteral::IsFastBuiltinBit::START_BIT, &lCallNativeCpp);
4974514f5e3Sopenharmony_ci            // 3 : 3 means call0 call1 call2 call3
4984514f5e3Sopenharmony_ci            __ Cmp(actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() + 3));
4994514f5e3Sopenharmony_ci            __ B(Condition::LE, &lCallBuiltinStub);
5004514f5e3Sopenharmony_ci        } else {
5014514f5e3Sopenharmony_ci            __ Tbnz(callField, MethodLiteral::IsFastBuiltinBit::START_BIT, &lCallBuiltinStub);
5024514f5e3Sopenharmony_ci        }
5034514f5e3Sopenharmony_ci        __ Bind(&lCallNativeCpp);
5044514f5e3Sopenharmony_ci        __ Ldr(nativeFuncAddr, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
5054514f5e3Sopenharmony_ci        CallBuiltinTrampoline(assembler);
5064514f5e3Sopenharmony_ci    }
5074514f5e3Sopenharmony_ci
5084514f5e3Sopenharmony_ci    __ Bind(&lCallBuiltinStub);
5094514f5e3Sopenharmony_ci    {
5104514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
5114514f5e3Sopenharmony_ci        Register builtinStub = __ TempRegister1();
5124514f5e3Sopenharmony_ci        __ Ldr(Register(X5), MemoryOperand(method, Method::EXTRA_LITERAL_INFO_OFFSET));  // get extra literal
5134514f5e3Sopenharmony_ci        __ And(Register(X5).W(), Register(X5).W(), LogicalImmediate::Create(0xff, RegWSize));
5144514f5e3Sopenharmony_ci        if (!isNew) {
5154514f5e3Sopenharmony_ci            __ Cmp(Register(X5).W(), Immediate(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST));
5164514f5e3Sopenharmony_ci            __ B(Condition::GE, &lCallNativeCpp);
5174514f5e3Sopenharmony_ci        }
5184514f5e3Sopenharmony_ci        __ Add(builtinStub, glue, Operand(Register(X5).W(), UXTW, FRAME_SLOT_SIZE_LOG2));
5194514f5e3Sopenharmony_ci        __ Ldr(builtinStub, MemoryOperand(builtinStub, JSThread::GlueData::GetBuiltinsStubEntriesOffset(false)));
5204514f5e3Sopenharmony_ci
5214514f5e3Sopenharmony_ci        __ Ldr(Register(X1), MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
5224514f5e3Sopenharmony_ci        __ Ldr(Register(X2), MemoryOperand(sp, DOUBLE_SLOT_SIZE));  // get jsfunc
5234514f5e3Sopenharmony_ci        __ Ldr(Register(X3), MemoryOperand(sp, TRIPLE_SLOT_SIZE));  // get newtarget
5244514f5e3Sopenharmony_ci        __ Ldr(Register(X4), MemoryOperand(sp, QUADRUPLE_SLOT_SIZE));  // get this
5254514f5e3Sopenharmony_ci        __ Ldr(Register(X5), MemoryOperand(sp, 0));  // get number args
5264514f5e3Sopenharmony_ci        __ Sub(Register(X5), Register(X5), Immediate(NUM_MANDATORY_JSFUNC_ARGS));
5274514f5e3Sopenharmony_ci        if (!isNew) {
5284514f5e3Sopenharmony_ci            Label lCall0;
5294514f5e3Sopenharmony_ci            Label lCall1;
5304514f5e3Sopenharmony_ci            Label lCall2;
5314514f5e3Sopenharmony_ci            Label lCall3;
5324514f5e3Sopenharmony_ci            Label lTailCall;
5334514f5e3Sopenharmony_ci            Register fp(X29);
5344514f5e3Sopenharmony_ci            __ Cmp(Register(X5), Immediate(0));
5354514f5e3Sopenharmony_ci            __ B(Condition::EQ, &lCall0);
5364514f5e3Sopenharmony_ci            __ Cmp(Register(X5), Immediate(1));
5374514f5e3Sopenharmony_ci            __ B(Condition::EQ, &lCall1);
5384514f5e3Sopenharmony_ci            __ Cmp(Register(X5), Immediate(2));  // 2: 2 args
5394514f5e3Sopenharmony_ci            __ B(Condition::EQ, &lCall2);
5404514f5e3Sopenharmony_ci            __ Cmp(Register(X5), Immediate(3));  // 3: 3 args
5414514f5e3Sopenharmony_ci            __ B(Condition::EQ, &lCall3);
5424514f5e3Sopenharmony_ci
5434514f5e3Sopenharmony_ci            __ Bind(&lCall0);
5444514f5e3Sopenharmony_ci            {
5454514f5e3Sopenharmony_ci                __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED));
5464514f5e3Sopenharmony_ci                __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
5474514f5e3Sopenharmony_ci                __ Str(Register(X7), MemoryOperand(sp, 0));  // reset arg2's position
5484514f5e3Sopenharmony_ci                __ B(&lTailCall);
5494514f5e3Sopenharmony_ci            }
5504514f5e3Sopenharmony_ci
5514514f5e3Sopenharmony_ci            __ Bind(&lCall1);
5524514f5e3Sopenharmony_ci            {
5534514f5e3Sopenharmony_ci                __ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE));
5544514f5e3Sopenharmony_ci                __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));  // reset x7
5554514f5e3Sopenharmony_ci                __ Str(Register(X7), MemoryOperand(sp, 0));  // reset arg2's position
5564514f5e3Sopenharmony_ci                __ B(&lTailCall);
5574514f5e3Sopenharmony_ci            }
5584514f5e3Sopenharmony_ci
5594514f5e3Sopenharmony_ci            __ Bind(&lCall2);
5604514f5e3Sopenharmony_ci            {
5614514f5e3Sopenharmony_ci                __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
5624514f5e3Sopenharmony_ci                __ Str(Register(X7), MemoryOperand(sp, 0));  // reset arg2's position
5634514f5e3Sopenharmony_ci                __ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE));
5644514f5e3Sopenharmony_ci                __ B(&lTailCall);
5654514f5e3Sopenharmony_ci            }
5664514f5e3Sopenharmony_ci
5674514f5e3Sopenharmony_ci            __ Bind(&lCall3);
5684514f5e3Sopenharmony_ci            __ Ldp(Register(X6), Register(X7), MemoryOperand(sp, QUINTUPLE_SLOT_SIZE));  // get arg0 arg1
5694514f5e3Sopenharmony_ci            PushAsmBridgeFrame(assembler);
5704514f5e3Sopenharmony_ci            {
5714514f5e3Sopenharmony_ci                // push arg2 and call
5724514f5e3Sopenharmony_ci                TempRegister2Scope scope2(assembler);
5734514f5e3Sopenharmony_ci                Register arg2 = __ TempRegister2();
5744514f5e3Sopenharmony_ci                __ Ldr(arg2, MemoryOperand(fp, NONUPLE_SLOT_SIZE));
5754514f5e3Sopenharmony_ci                __ Stp(arg2, Register(X8), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
5764514f5e3Sopenharmony_ci                __ Blr(builtinStub);
5774514f5e3Sopenharmony_ci                __ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE));
5784514f5e3Sopenharmony_ci            }
5794514f5e3Sopenharmony_ci            PopAsmBridgeFrame(assembler);
5804514f5e3Sopenharmony_ci            __ Ret();
5814514f5e3Sopenharmony_ci            __ Bind(&lTailCall);
5824514f5e3Sopenharmony_ci            {
5834514f5e3Sopenharmony_ci                __ Br(builtinStub);
5844514f5e3Sopenharmony_ci            }
5854514f5e3Sopenharmony_ci        } else {
5864514f5e3Sopenharmony_ci            Register argv(X6);
5874514f5e3Sopenharmony_ci            TempRegister2Scope scope2(assembler);
5884514f5e3Sopenharmony_ci            Register temp = __ TempRegister2();
5894514f5e3Sopenharmony_ci            CallBuiltinConstructorStub(assembler, builtinStub, argv, glue, temp);
5904514f5e3Sopenharmony_ci        }
5914514f5e3Sopenharmony_ci    }
5924514f5e3Sopenharmony_ci
5934514f5e3Sopenharmony_ci    Label jsBoundFunction;
5944514f5e3Sopenharmony_ci    Label jsProxy;
5954514f5e3Sopenharmony_ci    __ Bind(&notJSFunction);
5964514f5e3Sopenharmony_ci    {
5974514f5e3Sopenharmony_ci        Register bitfield(X2);
5984514f5e3Sopenharmony_ci        Register jstype2(X5, W);
5994514f5e3Sopenharmony_ci        __ And(jstype2, bitfield.W(), LogicalImmediate::Create(0xff, RegWSize));
6004514f5e3Sopenharmony_ci        __ Cmp(jstype2, Immediate(static_cast<int64_t>(JSType::JS_BOUND_FUNCTION)));
6014514f5e3Sopenharmony_ci        __ B(Condition::EQ, &jsBoundFunction);
6024514f5e3Sopenharmony_ci        __ Cmp(jstype2, Immediate(static_cast<int64_t>(JSType::JS_PROXY)));
6034514f5e3Sopenharmony_ci        __ B(Condition::EQ, &jsProxy);
6044514f5e3Sopenharmony_ci        __ Ret();
6054514f5e3Sopenharmony_ci    }
6064514f5e3Sopenharmony_ci
6074514f5e3Sopenharmony_ci    __ Bind(&jsBoundFunction);
6084514f5e3Sopenharmony_ci    {
6094514f5e3Sopenharmony_ci        JSBoundFunctionCallInternal(assembler, glue, actualArgC, jsfunc, RTSTUB_ID(JSCall));
6104514f5e3Sopenharmony_ci    }
6114514f5e3Sopenharmony_ci    __ Bind(&jsProxy);
6124514f5e3Sopenharmony_ci    {
6134514f5e3Sopenharmony_ci        __ Ldr(method, MemoryOperand(jsfunc, JSProxy::METHOD_OFFSET));
6144514f5e3Sopenharmony_ci        __ Ldr(callField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
6154514f5e3Sopenharmony_ci        __ Ldr(actualArgC, MemoryOperand(sp, 0));
6164514f5e3Sopenharmony_ci        __ B(&callNativeMethod);
6174514f5e3Sopenharmony_ci    }
6184514f5e3Sopenharmony_ci    __ Bind(&nonCallable);
6194514f5e3Sopenharmony_ci    {
6204514f5e3Sopenharmony_ci        ThrowNonCallableInternal(assembler, sp);
6214514f5e3Sopenharmony_ci    }
6224514f5e3Sopenharmony_ci    __ Bind(&lCallConstructor);
6234514f5e3Sopenharmony_ci    {
6244514f5e3Sopenharmony_ci        Register frameType(X6);
6254514f5e3Sopenharmony_ci        __ PushFpAndLr();
6264514f5e3Sopenharmony_ci        __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)));
6274514f5e3Sopenharmony_ci        // 2 : 2 means pair
6284514f5e3Sopenharmony_ci        __ Stp(Register(Zero), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
6294514f5e3Sopenharmony_ci        __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
6304514f5e3Sopenharmony_ci        Register argC(X5);
6314514f5e3Sopenharmony_ci        Register runtimeId(X6);
6324514f5e3Sopenharmony_ci        __ Mov(argC, Immediate(0));
6334514f5e3Sopenharmony_ci        __ Mov(runtimeId, Immediate(RTSTUB_ID(ThrowCallConstructorException)));
6344514f5e3Sopenharmony_ci        // 2 : 2 means pair
6354514f5e3Sopenharmony_ci        __ Stp(runtimeId, argC, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
6364514f5e3Sopenharmony_ci        __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
6374514f5e3Sopenharmony_ci        // 4 : 4 means stack slot
6384514f5e3Sopenharmony_ci        __ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE));
6394514f5e3Sopenharmony_ci        __ RestoreFpAndLr();
6404514f5e3Sopenharmony_ci        __ Ret();
6414514f5e3Sopenharmony_ci    }
6424514f5e3Sopenharmony_ci}
6434514f5e3Sopenharmony_ci
6444514f5e3Sopenharmony_ci// After the callee function of common aot call deopt, use this bridge to deal with this aot call.
6454514f5e3Sopenharmony_ci// calling convention: webkit_jsc
6464514f5e3Sopenharmony_ci// Input structure:
6474514f5e3Sopenharmony_ci// %X0 - glue
6484514f5e3Sopenharmony_ci// stack:
6494514f5e3Sopenharmony_ci// +--------------------------+
6504514f5e3Sopenharmony_ci// |       arg[N-1]           |
6514514f5e3Sopenharmony_ci// +--------------------------+
6524514f5e3Sopenharmony_ci// |       ...                |
6534514f5e3Sopenharmony_ci// +--------------------------+
6544514f5e3Sopenharmony_ci// |       arg[1]             |
6554514f5e3Sopenharmony_ci// +--------------------------+
6564514f5e3Sopenharmony_ci// |       arg[0]             |
6574514f5e3Sopenharmony_ci// +--------------------------+
6584514f5e3Sopenharmony_ci// |       this               |
6594514f5e3Sopenharmony_ci// +--------------------------+
6604514f5e3Sopenharmony_ci// |       new-target         |
6614514f5e3Sopenharmony_ci// +--------------------------+
6624514f5e3Sopenharmony_ci// |       call-target        |
6634514f5e3Sopenharmony_ci// |--------------------------|
6644514f5e3Sopenharmony_ci// |       argv               |
6654514f5e3Sopenharmony_ci// |--------------------------|
6664514f5e3Sopenharmony_ci// |       argc               |
6674514f5e3Sopenharmony_ci// +--------------------------+ <---- sp
6684514f5e3Sopenharmony_civoid OptimizedCall::AOTCallToAsmInterBridge(ExtendedAssembler *assembler)
6694514f5e3Sopenharmony_ci{
6704514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(AOTCallToAsmInterBridge));
6714514f5e3Sopenharmony_ci    Register sp(SP);
6724514f5e3Sopenharmony_ci    // params of c++ calling convention
6734514f5e3Sopenharmony_ci    Register glue(X0);
6744514f5e3Sopenharmony_ci    Register jsfunc(X1);
6754514f5e3Sopenharmony_ci    Register method(X2);
6764514f5e3Sopenharmony_ci    Register callField(X3);
6774514f5e3Sopenharmony_ci    Register actualArgC(X4);
6784514f5e3Sopenharmony_ci    Register argV(X5);
6794514f5e3Sopenharmony_ci
6804514f5e3Sopenharmony_ci    __ Ldr(jsfunc, MemoryOperand(sp, DOUBLE_SLOT_SIZE));
6814514f5e3Sopenharmony_ci    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
6824514f5e3Sopenharmony_ci    __ Ldr(callField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
6834514f5e3Sopenharmony_ci    __ Ldr(actualArgC, MemoryOperand(sp, 0));
6844514f5e3Sopenharmony_ci    // skip argc
6854514f5e3Sopenharmony_ci    __ Add(argV, sp, Immediate(kungfu::ArgumentAccessor::GetExtraArgsNum() * FRAME_SLOT_SIZE));
6864514f5e3Sopenharmony_ci    // asm interpreter argV = argv + 24
6874514f5e3Sopenharmony_ci    __ Add(argV, argV, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE));
6884514f5e3Sopenharmony_ci    __ Sub(actualArgC, actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()));
6894514f5e3Sopenharmony_ci    OptimizedCallAsmInterpreter(assembler);
6904514f5e3Sopenharmony_ci}
6914514f5e3Sopenharmony_ci
6924514f5e3Sopenharmony_ci// After the callee function of fast aot call deopt, use this bridge to deal with this fast aot call.
6934514f5e3Sopenharmony_ci// Notice: no argc and new-target params compared with not-fast aot call because these params are not needed
6944514f5e3Sopenharmony_ci// by bytecode-analysis
6954514f5e3Sopenharmony_ci// Intruduction: use expected argc as actual argc below for these reasons:
6964514f5e3Sopenharmony_ci// 1) when expected argc == actual argc, pass.
6974514f5e3Sopenharmony_ci// 2) when expected argc > actual argc, undefineds have been pushed in OptimizedFastCallAndPushArgv.
6984514f5e3Sopenharmony_ci// 3) when expected argc < actual argc, redundant params are useless according to bytecode-analysis, just abandon them.
6994514f5e3Sopenharmony_ci// calling convention: c++ calling convention
7004514f5e3Sopenharmony_ci// Input structure:
7014514f5e3Sopenharmony_ci// %X0 - glue
7024514f5e3Sopenharmony_ci// %X1 - call-target
7034514f5e3Sopenharmony_ci// %X2 - this
7044514f5e3Sopenharmony_ci// %X3 - arg0
7054514f5e3Sopenharmony_ci// %X4 - arg1
7064514f5e3Sopenharmony_ci// %X5 - arg2
7074514f5e3Sopenharmony_ci// %X6 - arg3
7084514f5e3Sopenharmony_ci// %X7 - arg4
7094514f5e3Sopenharmony_ci// stack:
7104514f5e3Sopenharmony_ci// +--------------------------+
7114514f5e3Sopenharmony_ci// |        arg[N-1]          |
7124514f5e3Sopenharmony_ci// +--------------------------+
7134514f5e3Sopenharmony_ci// |       ...                |
7144514f5e3Sopenharmony_ci// +--------------------------+
7154514f5e3Sopenharmony_ci// |       arg[5]             |
7164514f5e3Sopenharmony_ci// +--------------------------+ <---- sp
7174514f5e3Sopenharmony_civoid OptimizedCall::FastCallToAsmInterBridge(ExtendedAssembler *assembler)
7184514f5e3Sopenharmony_ci{
7194514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(FastCallToAsmInterBridge));
7204514f5e3Sopenharmony_ci
7214514f5e3Sopenharmony_ci    // Add a bridge frame to protect the stack map, because args will be put on the stack to construct argv on stack
7224514f5e3Sopenharmony_ci    // and the AsmInterpBridgeFrame pushed below cannot protect the stack map anymore.
7234514f5e3Sopenharmony_ci    PushAsmBridgeFrame(assembler);
7244514f5e3Sopenharmony_ci
7254514f5e3Sopenharmony_ci    Register sp(SP);
7264514f5e3Sopenharmony_ci    // Input
7274514f5e3Sopenharmony_ci    Register glue(X0);
7284514f5e3Sopenharmony_ci    Register jsfunc(X1);
7294514f5e3Sopenharmony_ci    Register thisReg(X2);
7304514f5e3Sopenharmony_ci
7314514f5e3Sopenharmony_ci    Register tempArgc = __ AvailableRegister1();
7324514f5e3Sopenharmony_ci    {
7334514f5e3Sopenharmony_ci        TempRegister2Scope scope2(assembler);
7344514f5e3Sopenharmony_ci        Register tempMethod = __ TempRegister2();
7354514f5e3Sopenharmony_ci
7364514f5e3Sopenharmony_ci        __ Ldr(tempMethod, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
7374514f5e3Sopenharmony_ci        __ Ldr(tempArgc, MemoryOperand(tempMethod, Method::CALL_FIELD_OFFSET));
7384514f5e3Sopenharmony_ci        __ Lsr(tempArgc, tempArgc, MethodLiteral::NumArgsBits::START_BIT);
7394514f5e3Sopenharmony_ci        __ And(tempArgc, tempArgc,
7404514f5e3Sopenharmony_ci            LogicalImmediate::Create(
7414514f5e3Sopenharmony_ci                MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize));
7424514f5e3Sopenharmony_ci    }
7434514f5e3Sopenharmony_ci    {
7444514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
7454514f5e3Sopenharmony_ci        Register startSp = __ TempRegister1();
7464514f5e3Sopenharmony_ci        __ Mov(startSp, sp);
7474514f5e3Sopenharmony_ci
7484514f5e3Sopenharmony_ci        Label lCall0;
7494514f5e3Sopenharmony_ci        Label lCall1;
7504514f5e3Sopenharmony_ci        Label lCall2;
7514514f5e3Sopenharmony_ci        Label lCall3;
7524514f5e3Sopenharmony_ci        Label lCall4;
7534514f5e3Sopenharmony_ci        Label lCall5;
7544514f5e3Sopenharmony_ci        Label lPushCommonRegs;
7554514f5e3Sopenharmony_ci
7564514f5e3Sopenharmony_ci        __ Cmp(tempArgc, Immediate(0));
7574514f5e3Sopenharmony_ci        __ B(Condition::EQ, &lCall0);
7584514f5e3Sopenharmony_ci        __ Cmp(tempArgc, Immediate(1));
7594514f5e3Sopenharmony_ci        __ B(Condition::EQ, &lCall1);
7604514f5e3Sopenharmony_ci        __ Cmp(tempArgc, Immediate(2));  // 2: 2 args
7614514f5e3Sopenharmony_ci        __ B(Condition::EQ, &lCall2);
7624514f5e3Sopenharmony_ci        __ Cmp(tempArgc, Immediate(3));  // 3: 3 args
7634514f5e3Sopenharmony_ci        __ B(Condition::EQ, &lCall3);
7644514f5e3Sopenharmony_ci        __ Cmp(tempArgc, Immediate(4));  // 4: 4 args
7654514f5e3Sopenharmony_ci        __ B(Condition::EQ, &lCall4);
7664514f5e3Sopenharmony_ci        __ Cmp(tempArgc, Immediate(5));  // 5: 5 args
7674514f5e3Sopenharmony_ci        __ B(Condition::EQ, &lCall5);
7684514f5e3Sopenharmony_ci        // default: more than 5 args
7694514f5e3Sopenharmony_ci        {
7704514f5e3Sopenharmony_ci            TempRegister2Scope scope2(assembler);
7714514f5e3Sopenharmony_ci            Register onStackArgs = __ TempRegister2();
7724514f5e3Sopenharmony_ci            Register op1 = __ AvailableRegister2();
7734514f5e3Sopenharmony_ci            Register op2 = __ AvailableRegister3();
7744514f5e3Sopenharmony_ci
7754514f5e3Sopenharmony_ci            // skip bridge frame, return addr and a callee save
7764514f5e3Sopenharmony_ci            __ Add(onStackArgs, sp, Immediate(QUADRUPLE_SLOT_SIZE));
7774514f5e3Sopenharmony_ci            __ Sub(tempArgc, tempArgc, Immediate(5));  // 5: the first 5 args are not on stack
7784514f5e3Sopenharmony_ci            Register arg4(X7);
7794514f5e3Sopenharmony_ci            PushArgsWithArgvInPair(assembler, tempArgc, onStackArgs, arg4, op1, op2, &lCall4);
7804514f5e3Sopenharmony_ci        }
7814514f5e3Sopenharmony_ci
7824514f5e3Sopenharmony_ci        __ Bind(&lCall0);
7834514f5e3Sopenharmony_ci        {
7844514f5e3Sopenharmony_ci            __ B(&lPushCommonRegs);
7854514f5e3Sopenharmony_ci        }
7864514f5e3Sopenharmony_ci
7874514f5e3Sopenharmony_ci        __ Bind(&lCall1);
7884514f5e3Sopenharmony_ci        {
7894514f5e3Sopenharmony_ci            __ Stp(Register(X3), Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
7904514f5e3Sopenharmony_ci            __ B(&lPushCommonRegs);
7914514f5e3Sopenharmony_ci        }
7924514f5e3Sopenharmony_ci
7934514f5e3Sopenharmony_ci        __ Bind(&lCall2);
7944514f5e3Sopenharmony_ci        {
7954514f5e3Sopenharmony_ci            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
7964514f5e3Sopenharmony_ci            __ B(&lPushCommonRegs);
7974514f5e3Sopenharmony_ci        }
7984514f5e3Sopenharmony_ci
7994514f5e3Sopenharmony_ci        __ Bind(&lCall3);
8004514f5e3Sopenharmony_ci        {
8014514f5e3Sopenharmony_ci            __ Stp(Register(X5), Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8024514f5e3Sopenharmony_ci            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8034514f5e3Sopenharmony_ci            __ B(&lPushCommonRegs);
8044514f5e3Sopenharmony_ci        }
8054514f5e3Sopenharmony_ci
8064514f5e3Sopenharmony_ci        __ Bind(&lCall4);
8074514f5e3Sopenharmony_ci        {
8084514f5e3Sopenharmony_ci            __ Stp(Register(X5), Register(X6), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8094514f5e3Sopenharmony_ci            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8104514f5e3Sopenharmony_ci            __ B(&lPushCommonRegs);
8114514f5e3Sopenharmony_ci        }
8124514f5e3Sopenharmony_ci
8134514f5e3Sopenharmony_ci        __ Bind(&lCall5);
8144514f5e3Sopenharmony_ci        {
8154514f5e3Sopenharmony_ci            __ Stp(Register(X7), Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8164514f5e3Sopenharmony_ci            __ Stp(Register(X5), Register(X6), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8174514f5e3Sopenharmony_ci            __ Stp(Register(X3), Register(X4), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8184514f5e3Sopenharmony_ci            __ B(&lPushCommonRegs);
8194514f5e3Sopenharmony_ci        }
8204514f5e3Sopenharmony_ci
8214514f5e3Sopenharmony_ci        __ Bind(&lPushCommonRegs);
8224514f5e3Sopenharmony_ci        {
8234514f5e3Sopenharmony_ci            Register newTarget(X7);
8244514f5e3Sopenharmony_ci            __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED));
8254514f5e3Sopenharmony_ci            __ Stp(newTarget, thisReg, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8264514f5e3Sopenharmony_ci            __ Stp(startSp, jsfunc, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
8274514f5e3Sopenharmony_ci            // fall through
8284514f5e3Sopenharmony_ci        }
8294514f5e3Sopenharmony_ci    }
8304514f5e3Sopenharmony_ci
8314514f5e3Sopenharmony_ci    // params of c++ calling convention
8324514f5e3Sopenharmony_ci    // glue: X0
8334514f5e3Sopenharmony_ci    // jsfunc: X1
8344514f5e3Sopenharmony_ci    Register method(X2);
8354514f5e3Sopenharmony_ci    Register methodCallField(X3);
8364514f5e3Sopenharmony_ci    Register argc(X4);
8374514f5e3Sopenharmony_ci    Register argV(X5);
8384514f5e3Sopenharmony_ci    // reload and prepare args for JSCallCommonEntry
8394514f5e3Sopenharmony_ci    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
8404514f5e3Sopenharmony_ci    __ Ldr(methodCallField, MemoryOperand(method, Method::CALL_FIELD_OFFSET));
8414514f5e3Sopenharmony_ci    __ Mov(argc, methodCallField);
8424514f5e3Sopenharmony_ci    __ Lsr(argc, argc, MethodLiteral::NumArgsBits::START_BIT);
8434514f5e3Sopenharmony_ci    __ And(argc, argc,
8444514f5e3Sopenharmony_ci        LogicalImmediate::Create(
8454514f5e3Sopenharmony_ci            MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize));
8464514f5e3Sopenharmony_ci    __ Add(argV, sp, Immediate((kungfu::ArgumentAccessor::GetFixArgsNum() + 1) * FRAME_SLOT_SIZE));  // 1: skip startSp
8474514f5e3Sopenharmony_ci
8484514f5e3Sopenharmony_ci    Label target;
8494514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
8504514f5e3Sopenharmony_ci    __ Bl(&target);
8514514f5e3Sopenharmony_ci    {
8524514f5e3Sopenharmony_ci        PopAsmInterpBridgeFrame(assembler);
8534514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
8544514f5e3Sopenharmony_ci        Register startSp = __ TempRegister1();
8554514f5e3Sopenharmony_ci        __ Ldp(startSp, Register(Zero), MemoryOperand(sp, ExtendedAssembler::PAIR_SLOT_SIZE, POSTINDEX));
8564514f5e3Sopenharmony_ci        __ Mov(sp, startSp);
8574514f5e3Sopenharmony_ci        PopAsmBridgeFrame(assembler);
8584514f5e3Sopenharmony_ci        __ Ret();
8594514f5e3Sopenharmony_ci    }
8604514f5e3Sopenharmony_ci    __ Bind(&target);
8614514f5e3Sopenharmony_ci    {
8624514f5e3Sopenharmony_ci        AsmInterpreterCall::JSCallCommonEntry(assembler, JSCallMode::CALL_FROM_AOT,
8634514f5e3Sopenharmony_ci                                              FrameTransitionType::OTHER_TO_OTHER);
8644514f5e3Sopenharmony_ci    }
8654514f5e3Sopenharmony_ci}
8664514f5e3Sopenharmony_ci
8674514f5e3Sopenharmony_civoid OptimizedCall::JSCallCheck(ExtendedAssembler *assembler, Register jsfunc, Register taggedValue,
8684514f5e3Sopenharmony_ci                                Label *nonCallable, Label *notJSFunction)
8694514f5e3Sopenharmony_ci{
8704514f5e3Sopenharmony_ci    __ Mov(taggedValue, JSTaggedValue::TAG_MARK);
8714514f5e3Sopenharmony_ci    __ Cmp(jsfunc, taggedValue);
8724514f5e3Sopenharmony_ci    __ B(Condition::HS, nonCallable);
8734514f5e3Sopenharmony_ci    __ Cbz(jsfunc, nonCallable);
8744514f5e3Sopenharmony_ci    __ Mov(taggedValue, JSTaggedValue::TAG_SPECIAL);
8754514f5e3Sopenharmony_ci    __ And(taggedValue, jsfunc, taggedValue);
8764514f5e3Sopenharmony_ci    __ Cbnz(taggedValue, nonCallable);
8774514f5e3Sopenharmony_ci
8784514f5e3Sopenharmony_ci    Register jshclass(X2);
8794514f5e3Sopenharmony_ci    __ Ldr(jshclass, MemoryOperand(jsfunc, JSFunction::HCLASS_OFFSET));
8804514f5e3Sopenharmony_ci    Register bitfield(X2);
8814514f5e3Sopenharmony_ci    __ Ldr(bitfield, MemoryOperand(jshclass, JSHClass::BIT_FIELD_OFFSET));
8824514f5e3Sopenharmony_ci    __ Tbz(bitfield, JSHClass::CallableBit::START_BIT, nonCallable);
8834514f5e3Sopenharmony_ci
8844514f5e3Sopenharmony_ci    Register jstype(X3, W);
8854514f5e3Sopenharmony_ci    __ And(jstype, bitfield, LogicalImmediate::Create(0xFF, RegWSize));
8864514f5e3Sopenharmony_ci    // 4 : 4 means JSType::JS_FUNCTION_FIRST
8874514f5e3Sopenharmony_ci    __ Sub(jstype, jstype, Immediate(static_cast<int>(JSType::JS_FUNCTION_FIRST)));
8884514f5e3Sopenharmony_ci    // 9 : 9 means JSType::JS_FUNCTION_LAST - JSType::JS_FUNCTION_FIRST + 1
8894514f5e3Sopenharmony_ci    __ Cmp(jstype, Immediate(static_cast<int>(JSType::JS_FUNCTION_LAST) -
8904514f5e3Sopenharmony_ci        static_cast<int>(JSType::JS_FUNCTION_FIRST) + 1));
8914514f5e3Sopenharmony_ci    __ B(Condition::HS, notJSFunction);
8924514f5e3Sopenharmony_ci}
8934514f5e3Sopenharmony_ci
8944514f5e3Sopenharmony_civoid OptimizedCall::ThrowNonCallableInternal(ExtendedAssembler *assembler, Register sp)
8954514f5e3Sopenharmony_ci{
8964514f5e3Sopenharmony_ci    Register frameType(X6);
8974514f5e3Sopenharmony_ci    Register taggedMessageId(X5);
8984514f5e3Sopenharmony_ci    __ PushFpAndLr();
8994514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)));
9004514f5e3Sopenharmony_ci    __ Mov(taggedMessageId,
9014514f5e3Sopenharmony_ci        Immediate(JSTaggedValue(GET_MESSAGE_STRING_ID(NonCallable)).GetRawData()));
9024514f5e3Sopenharmony_ci    // 2 : 2 means pair
9034514f5e3Sopenharmony_ci    __ Stp(taggedMessageId, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
9044514f5e3Sopenharmony_ci    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
9054514f5e3Sopenharmony_ci    Register argC(X5);
9064514f5e3Sopenharmony_ci    Register runtimeId(X6);
9074514f5e3Sopenharmony_ci    __ Mov(argC, Immediate(1));
9084514f5e3Sopenharmony_ci    __ Mov(runtimeId, Immediate(RTSTUB_ID(ThrowTypeError)));
9094514f5e3Sopenharmony_ci    // 2 : 2 means pair
9104514f5e3Sopenharmony_ci    __ Stp(runtimeId, argC, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
9114514f5e3Sopenharmony_ci    __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
9124514f5e3Sopenharmony_ci    __ Mov(Register(X0), Immediate(JSTaggedValue::VALUE_EXCEPTION));
9134514f5e3Sopenharmony_ci    // 4 : 4 means stack slot
9144514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE));
9154514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
9164514f5e3Sopenharmony_ci    __ Ret();
9174514f5e3Sopenharmony_ci}
9184514f5e3Sopenharmony_ci
9194514f5e3Sopenharmony_civoid OptimizedCall::JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register glue,
9204514f5e3Sopenharmony_ci                                                Register actualArgC, Register jsfunc, int stubId)
9214514f5e3Sopenharmony_ci{
9224514f5e3Sopenharmony_ci    // construct frame
9234514f5e3Sopenharmony_ci    PushOptimizedArgsConfigFrame(assembler);
9244514f5e3Sopenharmony_ci    Register basefp(X29);
9254514f5e3Sopenharmony_ci    Register fp = __ AvailableRegister1();
9264514f5e3Sopenharmony_ci
9274514f5e3Sopenharmony_ci    Register argV(X5);
9284514f5e3Sopenharmony_ci    __ Add(argV, basefp, Immediate(GetStackArgOffSetToFp(0))); // 0: first index id
9294514f5e3Sopenharmony_ci    __ Ldr(actualArgC, MemoryOperand(argV, 0));
9304514f5e3Sopenharmony_ci
9314514f5e3Sopenharmony_ci    Register boundLength(X2);
9324514f5e3Sopenharmony_ci    Register realArgC(X7, W);
9334514f5e3Sopenharmony_ci    Label copyBoundArgument;
9344514f5e3Sopenharmony_ci    Label pushCallTarget;
9354514f5e3Sopenharmony_ci    Label popArgs;
9364514f5e3Sopenharmony_ci    Label slowCall;
9374514f5e3Sopenharmony_ci    Label aotCall;
9384514f5e3Sopenharmony_ci    Label notClass;
9394514f5e3Sopenharmony_ci    // get bound arguments
9404514f5e3Sopenharmony_ci    __ Ldr(boundLength, MemoryOperand(jsfunc, JSBoundFunction::BOUND_ARGUMENTS_OFFSET));
9414514f5e3Sopenharmony_ci    //  get bound length
9424514f5e3Sopenharmony_ci    __ Ldr(boundLength, MemoryOperand(boundLength, TaggedArray::LENGTH_OFFSET));
9434514f5e3Sopenharmony_ci    __ Add(realArgC, boundLength.W(), actualArgC.W());
9444514f5e3Sopenharmony_ci    __ Mov(Register(X19), realArgC);
9454514f5e3Sopenharmony_ci    IncreaseStackForArguments(assembler, realArgC, fp, static_cast<int64_t>(CommonArgIdx::ACTUAL_ARGV));
9464514f5e3Sopenharmony_ci    __ Sub(actualArgC.W(), actualArgC.W(), Immediate(NUM_MANDATORY_JSFUNC_ARGS));
9474514f5e3Sopenharmony_ci    __ Cmp(actualArgC.W(), Immediate(0));
9484514f5e3Sopenharmony_ci    __ B(Condition::EQ, &copyBoundArgument);
9494514f5e3Sopenharmony_ci    {
9504514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
9514514f5e3Sopenharmony_ci        Register tmp = __ TempRegister1();
9524514f5e3Sopenharmony_ci        const int64_t argoffsetSlot = static_cast<int64_t>(CommonArgIdx::FUNC) - 1;
9534514f5e3Sopenharmony_ci        __ Add(argV, argV, Immediate((NUM_MANDATORY_JSFUNC_ARGS + argoffsetSlot) * FRAME_SLOT_SIZE));
9544514f5e3Sopenharmony_ci        PushArgsWithArgv(assembler, glue, actualArgC, argV, tmp, fp, nullptr, nullptr);
9554514f5e3Sopenharmony_ci    }
9564514f5e3Sopenharmony_ci    __ Bind(&copyBoundArgument);
9574514f5e3Sopenharmony_ci    {
9584514f5e3Sopenharmony_ci        Register boundArgs(X4);
9594514f5e3Sopenharmony_ci        __ Ldr(boundArgs, MemoryOperand(jsfunc, JSBoundFunction::BOUND_ARGUMENTS_OFFSET));
9604514f5e3Sopenharmony_ci        __ Add(boundArgs, boundArgs, Immediate(TaggedArray::DATA_OFFSET));
9614514f5e3Sopenharmony_ci        __ Cmp(boundLength.W(), Immediate(0));
9624514f5e3Sopenharmony_ci        __ B(Condition::EQ, &pushCallTarget);
9634514f5e3Sopenharmony_ci        {
9644514f5e3Sopenharmony_ci            TempRegister1Scope scope1(assembler);
9654514f5e3Sopenharmony_ci            Register tmp = __ TempRegister1();
9664514f5e3Sopenharmony_ci            PushArgsWithArgv(assembler, glue, boundLength, boundArgs, tmp, fp, nullptr, nullptr);
9674514f5e3Sopenharmony_ci        }
9684514f5e3Sopenharmony_ci    }
9694514f5e3Sopenharmony_ci    Register boundTarget(X7);
9704514f5e3Sopenharmony_ci    Register newTarget(X6);
9714514f5e3Sopenharmony_ci    __ Bind(&pushCallTarget);
9724514f5e3Sopenharmony_ci    {
9734514f5e3Sopenharmony_ci        Register thisObj(X4);
9744514f5e3Sopenharmony_ci        __ Ldr(thisObj, MemoryOperand(jsfunc, JSBoundFunction::BOUND_THIS_OFFSET));
9754514f5e3Sopenharmony_ci        __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED));
9764514f5e3Sopenharmony_ci        // 2 : 2 means pair
9774514f5e3Sopenharmony_ci        __ Stp(newTarget, thisObj, MemoryOperand(fp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
9784514f5e3Sopenharmony_ci        __ Ldr(boundTarget, MemoryOperand(jsfunc, JSBoundFunction::BOUND_TARGET_OFFSET));
9794514f5e3Sopenharmony_ci        // 2 : 2 means pair
9804514f5e3Sopenharmony_ci        __ Stp(argV, boundTarget, MemoryOperand(fp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
9814514f5e3Sopenharmony_ci        __ Str(Register(X19), MemoryOperand(fp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
9824514f5e3Sopenharmony_ci    }
9834514f5e3Sopenharmony_ci    JSCallCheck(assembler, boundTarget, Register(X9), &slowCall, &slowCall);
9844514f5e3Sopenharmony_ci    Register hclass = __ AvailableRegister2();
9854514f5e3Sopenharmony_ci    __ Ldr(hclass, MemoryOperand(boundTarget, 0));
9864514f5e3Sopenharmony_ci    __ Ldr(hclass, MemoryOperand(hclass, JSHClass::BIT_FIELD_OFFSET));
9874514f5e3Sopenharmony_ci    __ Tbz(hclass, JSHClass::IsClassConstructorOrPrototypeBit::START_BIT, &notClass);
9884514f5e3Sopenharmony_ci    __ Tbnz(hclass, JSHClass::ConstructorBit::START_BIT, &slowCall);
9894514f5e3Sopenharmony_ci    __ Bind(&notClass);
9904514f5e3Sopenharmony_ci    Register compiledCodeFlag(X9, W);
9914514f5e3Sopenharmony_ci    __ Ldrh(compiledCodeFlag, MemoryOperand(boundTarget, JSFunctionBase::BIT_FIELD_OFFSET));
9924514f5e3Sopenharmony_ci    __ Tbz(compiledCodeFlag, JSFunctionBase::IsCompiledCodeBit::START_BIT, &slowCall);
9934514f5e3Sopenharmony_ci    __ Bind(&aotCall);
9944514f5e3Sopenharmony_ci    {
9954514f5e3Sopenharmony_ci        // output: glue:x0 argc:x1 calltarget:x2 argv:x3 this:x4 newtarget:x5
9964514f5e3Sopenharmony_ci        __ Mov(Register(X1), Register(X19));
9974514f5e3Sopenharmony_ci        __ Mov(Register(X2), boundTarget);
9984514f5e3Sopenharmony_ci        __ Add(X3, fp, Immediate(5 * FRAME_SLOT_SIZE)); // 5: skip argc and argv func new this
9994514f5e3Sopenharmony_ci        __ Mov(Register(X5), Register(X6));
10004514f5e3Sopenharmony_ci        Register boundCallInternalId(X9);
10014514f5e3Sopenharmony_ci        Register baseAddress(X8);
10024514f5e3Sopenharmony_ci        Register codeAddress(X10);
10034514f5e3Sopenharmony_ci        __ Mov(baseAddress, Immediate(JSThread::GlueData::GetCOStubEntriesOffset(false)));
10044514f5e3Sopenharmony_ci        __ Mov(boundCallInternalId, Immediate(CommonStubCSigns::JsBoundCallInternal));
10054514f5e3Sopenharmony_ci        __ Add(codeAddress, X0, baseAddress);
10064514f5e3Sopenharmony_ci        __ Ldr(codeAddress, MemoryOperand(codeAddress, boundCallInternalId, UXTW, FRAME_SLOT_SIZE_LOG2));
10074514f5e3Sopenharmony_ci        __ Blr(codeAddress);
10084514f5e3Sopenharmony_ci        __ B(&popArgs);
10094514f5e3Sopenharmony_ci    }
10104514f5e3Sopenharmony_ci    __ Bind(&slowCall);
10114514f5e3Sopenharmony_ci    {
10124514f5e3Sopenharmony_ci        __ CallAssemblerStub(stubId, false);
10134514f5e3Sopenharmony_ci        __ B(&popArgs);
10144514f5e3Sopenharmony_ci    }
10154514f5e3Sopenharmony_ci
10164514f5e3Sopenharmony_ci    __ Bind(&popArgs);
10174514f5e3Sopenharmony_ci    PopJSFunctionArgs(assembler, Register(X19), Register(X19));
10184514f5e3Sopenharmony_ci    PopOptimizedArgsConfigFrame(assembler);
10194514f5e3Sopenharmony_ci    __ Ret();
10204514f5e3Sopenharmony_ci}
10214514f5e3Sopenharmony_ci
10224514f5e3Sopenharmony_ci// * uint64_t JSProxyCallInternalWithArgV(uintptr_t glue, JSTaggedType calltarget)
10234514f5e3Sopenharmony_ci// * c++ calling convention call js function
10244514f5e3Sopenharmony_ci// * Arguments:
10254514f5e3Sopenharmony_ci//        %x0 - glue
10264514f5e3Sopenharmony_ci//        %x1 - calltarget
10274514f5e3Sopenharmony_ci
10284514f5e3Sopenharmony_civoid OptimizedCall::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler)
10294514f5e3Sopenharmony_ci{
10304514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(JSProxyCallInternalWithArgV));
10314514f5e3Sopenharmony_ci    Register jsfunc(X1);
10324514f5e3Sopenharmony_ci    Register sp(SP);
10334514f5e3Sopenharmony_ci    __ Str(jsfunc, MemoryOperand(sp, DOUBLE_SLOT_SIZE));
10344514f5e3Sopenharmony_ci    JSCallInternal(assembler, jsfunc);
10354514f5e3Sopenharmony_ci}
10364514f5e3Sopenharmony_ci
10374514f5e3Sopenharmony_ci// * uint64_t CallRuntimeWithArgv(uintptr_t glue, uint64_t runtime_id, uint64_t argc, uintptr_t argv)
10384514f5e3Sopenharmony_ci// * cc calling convention call runtime_id's runtion function(c-abi)
10394514f5e3Sopenharmony_ci// * Arguments:
10404514f5e3Sopenharmony_ci//         %x0 - glue
10414514f5e3Sopenharmony_ci//         %x1 - runtime_id
10424514f5e3Sopenharmony_ci//         %x2 - argc
10434514f5e3Sopenharmony_ci//         %x3 - argv
10444514f5e3Sopenharmony_ci//
10454514f5e3Sopenharmony_ci// * Optimized-leaved-frame-with-argv layout as the following:
10464514f5e3Sopenharmony_ci//         +--------------------------+
10474514f5e3Sopenharmony_ci//         |       argv[]             |
10484514f5e3Sopenharmony_ci//         +--------------------------+-------------
10494514f5e3Sopenharmony_ci//         |       argc               |            ^
10504514f5e3Sopenharmony_ci//         |--------------------------|            |
10514514f5e3Sopenharmony_ci//         |       RuntimeId          |   OptimizedWithArgvLeaveFrame
10524514f5e3Sopenharmony_ci//  sp --> |--------------------------|            |
10534514f5e3Sopenharmony_ci//         |       returnAddr         |            |
10544514f5e3Sopenharmony_ci//         |--------------------------|            |
10554514f5e3Sopenharmony_ci//         |       callsiteFp         |            |
10564514f5e3Sopenharmony_ci//         |--------------------------|            |
10574514f5e3Sopenharmony_ci//         |       frameType          |            v
10584514f5e3Sopenharmony_ci//         +--------------------------+-------------
10594514f5e3Sopenharmony_ci
10604514f5e3Sopenharmony_civoid OptimizedCall::CallRuntimeWithArgv(ExtendedAssembler *assembler)
10614514f5e3Sopenharmony_ci{
10624514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallRuntimeWithArgv));
10634514f5e3Sopenharmony_ci    Register glue(X0);
10644514f5e3Sopenharmony_ci    Register runtimeId(X1);
10654514f5e3Sopenharmony_ci    Register argc(X2);
10664514f5e3Sopenharmony_ci    Register argv(X3);
10674514f5e3Sopenharmony_ci    Register sp(SP);
10684514f5e3Sopenharmony_ci    // 2 : 2 means pair
10694514f5e3Sopenharmony_ci    __ Stp(argc, argv, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
10704514f5e3Sopenharmony_ci    __ Stp(Register(X30), runtimeId, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); // 2 : 2 means pair
10714514f5e3Sopenharmony_ci    Register fp(X29);
10724514f5e3Sopenharmony_ci    // construct leave frame
10734514f5e3Sopenharmony_ci    Register frameType(X9);
10744514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::LEAVE_FRAME_WITH_ARGV)));
10754514f5e3Sopenharmony_ci    __ Stp(frameType, Register(X29), MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); // 2 : 2 means pair
10764514f5e3Sopenharmony_ci    __ Add(Register(FP), sp, Immediate(FRAME_SLOT_SIZE));
10774514f5e3Sopenharmony_ci    __ Str(fp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
10784514f5e3Sopenharmony_ci
10794514f5e3Sopenharmony_ci     // load runtime trampoline address
10804514f5e3Sopenharmony_ci    Register tmp(X9);
10814514f5e3Sopenharmony_ci    Register rtfunc(X9);
10824514f5e3Sopenharmony_ci    // 3 : 3 means 2 << 3 = 8
10834514f5e3Sopenharmony_ci    __ Add(tmp, glue, Operand(runtimeId, LSL, 3));
10844514f5e3Sopenharmony_ci    __ Ldr(rtfunc, MemoryOperand(tmp, JSThread::GlueData::GetRTStubEntriesOffset(false)));
10854514f5e3Sopenharmony_ci    __ Mov(X1, argc);
10864514f5e3Sopenharmony_ci    __ Mov(X2, argv);
10874514f5e3Sopenharmony_ci    __ Blr(rtfunc);
10884514f5e3Sopenharmony_ci    __ Ldp(Register(Zero), Register(X29), MemoryOperand(sp, ExtendedAssembler::PAIR_SLOT_SIZE, POSTINDEX));
10894514f5e3Sopenharmony_ci    __ Ldp(Register(X30), Register(Zero), MemoryOperand(sp, ExtendedAssembler::PAIR_SLOT_SIZE, POSTINDEX));
10904514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE)); // 2 : 2 means pair
10914514f5e3Sopenharmony_ci    __ Ret();
10924514f5e3Sopenharmony_ci}
10934514f5e3Sopenharmony_ci
10944514f5e3Sopenharmony_civoid OptimizedCall::PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc,
10954514f5e3Sopenharmony_ci                                        Register thisObj, Register newTarget, Register currentSp)
10964514f5e3Sopenharmony_ci{
10974514f5e3Sopenharmony_ci    __ Str(thisObj, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
10984514f5e3Sopenharmony_ci    __ Str(newTarget, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
10994514f5e3Sopenharmony_ci    __ Str(jsfunc, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
11004514f5e3Sopenharmony_ci}
11014514f5e3Sopenharmony_ci
11024514f5e3Sopenharmony_civoid OptimizedCall::PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs)
11034514f5e3Sopenharmony_ci{
11044514f5e3Sopenharmony_ci    Register sp(SP);
11054514f5e3Sopenharmony_ci    Register fp(X6);
11064514f5e3Sopenharmony_ci    Label aligned;
11074514f5e3Sopenharmony_ci    const int64_t argoffsetSlot = static_cast<int64_t>(CommonArgIdx::FUNC) - 1;
11084514f5e3Sopenharmony_ci    if (expectedNumArgs != actualNumArgs) {
11094514f5e3Sopenharmony_ci        TempRegister1Scope scop1(assembler);
11104514f5e3Sopenharmony_ci        Register tmp = __ TempRegister1();
11114514f5e3Sopenharmony_ci        __ Cmp(expectedNumArgs, actualNumArgs);
11124514f5e3Sopenharmony_ci        __ CMov(tmp, expectedNumArgs, actualNumArgs, Condition::HI);
11134514f5e3Sopenharmony_ci        __ Add(sp, sp, Operand(tmp, UXTW, FRAME_SLOT_SIZE_LOG2));
11144514f5e3Sopenharmony_ci    } else {
11154514f5e3Sopenharmony_ci        __ Add(sp, sp, Operand(expectedNumArgs, UXTW, FRAME_SLOT_SIZE_LOG2));
11164514f5e3Sopenharmony_ci    }
11174514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(argoffsetSlot * FRAME_SLOT_SIZE));
11184514f5e3Sopenharmony_ci    __ Mov(fp, sp);
11194514f5e3Sopenharmony_ci    __ Tst(fp, LogicalImmediate::Create(0xf, RegXSize));  // 0xf: 0x1111
11204514f5e3Sopenharmony_ci    __ B(Condition::EQ, &aligned);
11214514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE));
11224514f5e3Sopenharmony_ci    __ Bind(&aligned);
11234514f5e3Sopenharmony_ci}
11244514f5e3Sopenharmony_ci
11254514f5e3Sopenharmony_civoid OptimizedCall::PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp)
11264514f5e3Sopenharmony_ci{
11274514f5e3Sopenharmony_ci    Register fp(X29);
11284514f5e3Sopenharmony_ci    Register sp(SP);
11294514f5e3Sopenharmony_ci    TempRegister2Scope temp2Scope(assembler);
11304514f5e3Sopenharmony_ci    __ PushFpAndLr();
11314514f5e3Sopenharmony_ci    Register frameType = __ TempRegister2();
11324514f5e3Sopenharmony_ci    // construct frame
11334514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_ENTRY_FRAME)));
11344514f5e3Sopenharmony_ci    // 2 : 2 means pairs
11354514f5e3Sopenharmony_ci    __ Stp(prevFp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
11364514f5e3Sopenharmony_ci    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
11374514f5e3Sopenharmony_ci    __ CalleeSave();
11384514f5e3Sopenharmony_ci}
11394514f5e3Sopenharmony_ci
11404514f5e3Sopenharmony_civoid OptimizedCall::PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue)
11414514f5e3Sopenharmony_ci{
11424514f5e3Sopenharmony_ci    Register fp(X29);
11434514f5e3Sopenharmony_ci    Register sp(SP);
11444514f5e3Sopenharmony_ci    Register prevFp(X1);
11454514f5e3Sopenharmony_ci    __ CalleeRestore();
11464514f5e3Sopenharmony_ci
11474514f5e3Sopenharmony_ci    // 2: prevFp and frameType
11484514f5e3Sopenharmony_ci    __ Ldp(prevFp, Register(Zero), MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX));
11494514f5e3Sopenharmony_ci    // restore return address
11504514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
11514514f5e3Sopenharmony_ci    __ Str(prevFp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
11524514f5e3Sopenharmony_ci}
11534514f5e3Sopenharmony_ci
11544514f5e3Sopenharmony_civoid OptimizedCall::PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler)
11554514f5e3Sopenharmony_ci{
11564514f5e3Sopenharmony_ci    Register sp(SP);
11574514f5e3Sopenharmony_ci    TempRegister2Scope temp2Scope(assembler);
11584514f5e3Sopenharmony_ci    Register frameType = __ TempRegister2();
11594514f5e3Sopenharmony_ci    __ PushFpAndLr();
11604514f5e3Sopenharmony_ci    // construct frame
11614514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)));
11624514f5e3Sopenharmony_ci    // 2 : 2 means pairs. X19 means calleesave and 16bytes align
11634514f5e3Sopenharmony_ci    __ Stp(Register(X19), frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
11644514f5e3Sopenharmony_ci    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
11654514f5e3Sopenharmony_ci}
11664514f5e3Sopenharmony_ci
11674514f5e3Sopenharmony_civoid OptimizedCall::PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler)
11684514f5e3Sopenharmony_ci{
11694514f5e3Sopenharmony_ci    TempRegister2Scope temp2Scope(assembler);
11704514f5e3Sopenharmony_ci    Register sp(SP);
11714514f5e3Sopenharmony_ci    Register frameType = __ TempRegister2();
11724514f5e3Sopenharmony_ci    // 2 : 2 means pop call site sp and type
11734514f5e3Sopenharmony_ci    __ Ldp(Register(X19), frameType, MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX));
11744514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
11754514f5e3Sopenharmony_ci}
11764514f5e3Sopenharmony_ci
11774514f5e3Sopenharmony_ci// * uint64_t PushOptimizedUnfoldArgVFrame(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
11784514f5e3Sopenharmony_ci//                                         JSTaggedType new, JSTaggedType this, JSTaggedType argV[])
11794514f5e3Sopenharmony_ci// * cc calling convention call js function()
11804514f5e3Sopenharmony_ci// * arguments:
11814514f5e3Sopenharmony_ci//              %x0 - glue
11824514f5e3Sopenharmony_ci//              %x1 - argc
11834514f5e3Sopenharmony_ci//              %x2 - call-target
11844514f5e3Sopenharmony_ci//              %x3 - new-target
11854514f5e3Sopenharmony_ci//              %x4 - this
11864514f5e3Sopenharmony_ci//              %x5 - argv
11874514f5e3Sopenharmony_ci//
11884514f5e3Sopenharmony_ci// * OptimizedUnfoldArgVFrame layout description as the following:
11894514f5e3Sopenharmony_ci//      sp ----> |--------------------------| ---------------
11904514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
11914514f5e3Sopenharmony_ci//  currentFp--> |--------------------------|               |
11924514f5e3Sopenharmony_ci//               |       prevFp             |               |
11934514f5e3Sopenharmony_ci//               |--------------------------|   OptimizedUnfoldArgVFrame
11944514f5e3Sopenharmony_ci//               |       frameType          |               |
11954514f5e3Sopenharmony_ci//               |--------------------------|               |
11964514f5e3Sopenharmony_ci//               |       currentFp          |               v
11974514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
11984514f5e3Sopenharmony_ci
11994514f5e3Sopenharmony_civoid OptimizedCall::PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp)
12004514f5e3Sopenharmony_ci{
12014514f5e3Sopenharmony_ci    Register sp(SP);
12024514f5e3Sopenharmony_ci    TempRegister2Scope temp2Scope(assembler);
12034514f5e3Sopenharmony_ci    Register frameType = __ TempRegister2();
12044514f5e3Sopenharmony_ci    __ PushFpAndLr();
12054514f5e3Sopenharmony_ci    // construct frame
12064514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME)));
12074514f5e3Sopenharmony_ci    // 2 : 2 means pairs
12084514f5e3Sopenharmony_ci    __ Stp(callSiteSp, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
12094514f5e3Sopenharmony_ci    __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
12104514f5e3Sopenharmony_ci}
12114514f5e3Sopenharmony_ci
12124514f5e3Sopenharmony_civoid OptimizedCall::PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler)
12134514f5e3Sopenharmony_ci{
12144514f5e3Sopenharmony_ci    Register sp(SP);
12154514f5e3Sopenharmony_ci    // 2 : 2 means pop call site sp and type
12164514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
12174514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
12184514f5e3Sopenharmony_ci}
12194514f5e3Sopenharmony_ci
12204514f5e3Sopenharmony_ci// * uint64_t JSCallWithArgV(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
12214514f5e3Sopenharmony_ci//                          JSTaggedType new, JSTaggedType this, argV)
12224514f5e3Sopenharmony_ci// * cc calling convention call js function()
12234514f5e3Sopenharmony_ci// * arguments:
12244514f5e3Sopenharmony_ci//              %x0 - glue
12254514f5e3Sopenharmony_ci//              %x1 - argc
12264514f5e3Sopenharmony_ci//              %x2 - call-target
12274514f5e3Sopenharmony_ci//              %x3 - new-target
12284514f5e3Sopenharmony_ci//              %x4 - this
12294514f5e3Sopenharmony_ci//              %x5 - argV[]
12304514f5e3Sopenharmony_ci//
12314514f5e3Sopenharmony_ci// * OptimizedJSFunctionFrame layout description as the following:
12324514f5e3Sopenharmony_ci//               +--------------------------+
12334514f5e3Sopenharmony_ci//               |       argn               |
12344514f5e3Sopenharmony_ci//               |--------------------------|
12354514f5e3Sopenharmony_ci//               |       argn - 1           |
12364514f5e3Sopenharmony_ci//               |--------------------------|
12374514f5e3Sopenharmony_ci//               |       .....              |
12384514f5e3Sopenharmony_ci//               |--------------------------|
12394514f5e3Sopenharmony_ci//               |       arg2               |
12404514f5e3Sopenharmony_ci//               |--------------------------|
12414514f5e3Sopenharmony_ci//               |       arg1               |
12424514f5e3Sopenharmony_ci//      sp ----> |--------------------------| ---------------
12434514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
12444514f5e3Sopenharmony_ci//               |--------------------------|               |
12454514f5e3Sopenharmony_ci//               |       callsiteFp         |               |
12464514f5e3Sopenharmony_ci//               |--------------------------|  OptimizedJSFunctionFrame
12474514f5e3Sopenharmony_ci//               |       frameType          |               |
12484514f5e3Sopenharmony_ci//               |--------------------------|               |
12494514f5e3Sopenharmony_ci//               |       call-target        |               v
12504514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
12514514f5e3Sopenharmony_ci
12524514f5e3Sopenharmony_civoid OptimizedCall::GenJSCallWithArgV(ExtendedAssembler *assembler, int id)
12534514f5e3Sopenharmony_ci{
12544514f5e3Sopenharmony_ci    Register sp(SP);
12554514f5e3Sopenharmony_ci    Register glue(X0);
12564514f5e3Sopenharmony_ci    Register actualNumArgs(X1);
12574514f5e3Sopenharmony_ci    Register jsfunc(X2);
12584514f5e3Sopenharmony_ci    Register newTarget(X3);
12594514f5e3Sopenharmony_ci    Register thisObj(X4);
12604514f5e3Sopenharmony_ci    Register argV(X5);
12614514f5e3Sopenharmony_ci    Register currentSp = __ AvailableRegister1();
12624514f5e3Sopenharmony_ci    Register callsiteSp = __ AvailableRegister2();
12634514f5e3Sopenharmony_ci    Label pushCallThis;
12644514f5e3Sopenharmony_ci
12654514f5e3Sopenharmony_ci    __ Mov(callsiteSp, sp);
12664514f5e3Sopenharmony_ci    PushOptimizedUnfoldArgVFrame(assembler, callsiteSp);
12674514f5e3Sopenharmony_ci    Register argC(X7);
12684514f5e3Sopenharmony_ci    __ Add(actualNumArgs, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
12694514f5e3Sopenharmony_ci    __ Mov(argC, actualNumArgs);
12704514f5e3Sopenharmony_ci    IncreaseStackForArguments(assembler, argC, currentSp, static_cast<int64_t>(CommonArgIdx::ACTUAL_ARGV));
12714514f5e3Sopenharmony_ci    {
12724514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
12734514f5e3Sopenharmony_ci        TempRegister2Scope scope2(assembler);
12744514f5e3Sopenharmony_ci        Register tmp = __ TempRegister1();
12754514f5e3Sopenharmony_ci        Register op = __ TempRegister2();
12764514f5e3Sopenharmony_ci        __ Sub(tmp, actualNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
12774514f5e3Sopenharmony_ci        PushArgsWithArgv(assembler, glue, tmp, argV, op, currentSp, &pushCallThis, nullptr);
12784514f5e3Sopenharmony_ci    }
12794514f5e3Sopenharmony_ci    __ Bind(&pushCallThis);
12804514f5e3Sopenharmony_ci    PushMandatoryJSArgs(assembler, jsfunc, thisObj, newTarget, currentSp);
12814514f5e3Sopenharmony_ci    {
12824514f5e3Sopenharmony_ci        TempRegister1Scope scope1(assembler);
12834514f5e3Sopenharmony_ci        Register tmp = __ TempRegister1();
12844514f5e3Sopenharmony_ci        __ Mov(tmp, currentSp);
12854514f5e3Sopenharmony_ci        __ Str(tmp, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
12864514f5e3Sopenharmony_ci        __ Str(actualNumArgs, MemoryOperand(currentSp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
12874514f5e3Sopenharmony_ci    }
12884514f5e3Sopenharmony_ci    __ CallAssemblerStub(id, false);
12894514f5e3Sopenharmony_ci    __ Ldr(actualNumArgs, MemoryOperand(sp, 0));
12904514f5e3Sopenharmony_ci    PopJSFunctionArgs(assembler, actualNumArgs, actualNumArgs);
12914514f5e3Sopenharmony_ci    PopOptimizedUnfoldArgVFrame(assembler);
12924514f5e3Sopenharmony_ci    __ Ret();
12934514f5e3Sopenharmony_ci}
12944514f5e3Sopenharmony_ci
12954514f5e3Sopenharmony_ci// * uint64_t JSCallWithArgVAndPushArgv(uintptr_t glue, uint32_t argc, JSTaggedType calltarget,
12964514f5e3Sopenharmony_ci//                          JSTaggedType new, JSTaggedType this, argV)
12974514f5e3Sopenharmony_ci// * cc calling convention call js function()
12984514f5e3Sopenharmony_ci// * arguments:
12994514f5e3Sopenharmony_ci//              %x0 - glue
13004514f5e3Sopenharmony_ci//              %x1 - argc
13014514f5e3Sopenharmony_ci//              %x2 - call-target
13024514f5e3Sopenharmony_ci//              %x3 - new-target
13034514f5e3Sopenharmony_ci//              %x4  - this
13044514f5e3Sopenharmony_ci//              %x5  - argv
13054514f5e3Sopenharmony_civoid OptimizedCall::JSCallWithArgVAndPushArgv(ExtendedAssembler *assembler)
13064514f5e3Sopenharmony_ci{
13074514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(JSCallWithArgVAndPushArgv));
13084514f5e3Sopenharmony_ci    GenJSCallWithArgV(assembler, RTSTUB_ID(OptimizedCallAndPushArgv));
13094514f5e3Sopenharmony_ci}
13104514f5e3Sopenharmony_ci
13114514f5e3Sopenharmony_civoid OptimizedCall::JSCallWithArgV(ExtendedAssembler *assembler)
13124514f5e3Sopenharmony_ci{
13134514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(JSCallWithArgV));
13144514f5e3Sopenharmony_ci    GenJSCallWithArgV(assembler, RTSTUB_ID(CallOptimized));
13154514f5e3Sopenharmony_ci}
13164514f5e3Sopenharmony_ci
13174514f5e3Sopenharmony_civoid OptimizedCall::SuperCallWithArgV(ExtendedAssembler *assembler)
13184514f5e3Sopenharmony_ci{
13194514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(SuperCallWithArgV));
13204514f5e3Sopenharmony_ci    GenJSCallWithArgV(assembler, RTSTUB_ID(JSCallNew));
13214514f5e3Sopenharmony_ci}
13224514f5e3Sopenharmony_ci
13234514f5e3Sopenharmony_civoid OptimizedCall::CallOptimized(ExtendedAssembler *assembler)
13244514f5e3Sopenharmony_ci{
13254514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallOptimized));
13264514f5e3Sopenharmony_ci    Register sp(SP);
13274514f5e3Sopenharmony_ci    Register jsfunc(X7);
13284514f5e3Sopenharmony_ci    Register method(X6);
13294514f5e3Sopenharmony_ci    Register codeAddr(X5);
13304514f5e3Sopenharmony_ci    auto funcSlotOffset = kungfu::ArgumentAccessor::GetExtraArgsNum();
13314514f5e3Sopenharmony_ci    __ Ldr(jsfunc, MemoryOperand(sp, funcSlotOffset * FRAME_SLOT_SIZE));
13324514f5e3Sopenharmony_ci    __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET));
13334514f5e3Sopenharmony_ci    __ Ldr(codeAddr, MemoryOperand(jsfunc, JSFunction::CODE_ENTRY_OFFSET));
13344514f5e3Sopenharmony_ci    __ Br(codeAddr);
13354514f5e3Sopenharmony_ci}
13364514f5e3Sopenharmony_ci
13374514f5e3Sopenharmony_civoid OptimizedCall::DeoptEnterAsmInterp(ExtendedAssembler *assembler)
13384514f5e3Sopenharmony_ci{
13394514f5e3Sopenharmony_ci    // rdi
13404514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
13414514f5e3Sopenharmony_ci    Register context(X2);
13424514f5e3Sopenharmony_ci    Register opRegister(X9);
13434514f5e3Sopenharmony_ci    Register outputCount(X10);
13444514f5e3Sopenharmony_ci    Register frameStateBase(X11);
13454514f5e3Sopenharmony_ci    Register currentSlotRegister(X12);
13464514f5e3Sopenharmony_ci    Register sp(SP);
13474514f5e3Sopenharmony_ci    Register depth(X20);
13484514f5e3Sopenharmony_ci    Register tmpReg(X21);
13494514f5e3Sopenharmony_ci    Label loopBegin;
13504514f5e3Sopenharmony_ci    Label stackOverflow;
13514514f5e3Sopenharmony_ci    Label pushArgv;
13524514f5e3Sopenharmony_ci
13534514f5e3Sopenharmony_ci    __ PushFpAndLr();
13544514f5e3Sopenharmony_ci
13554514f5e3Sopenharmony_ci    __ Ldr(depth, MemoryOperand(context, AsmStackContext::GetInlineDepthOffset(false)));
13564514f5e3Sopenharmony_ci    __ Add(context, context, Immediate(AsmStackContext::GetSize(false)));
13574514f5e3Sopenharmony_ci    __ Mov(Register(X23), Immediate(0));
13584514f5e3Sopenharmony_ci    // update fp
13594514f5e3Sopenharmony_ci    __ Mov(currentSlotRegister, sp);
13604514f5e3Sopenharmony_ci    __ Bind(&loopBegin);
13614514f5e3Sopenharmony_ci    __ Ldr(outputCount, MemoryOperand(context, 0));
13624514f5e3Sopenharmony_ci    __ Add(frameStateBase, context, Immediate(FRAME_SLOT_SIZE));
13634514f5e3Sopenharmony_ci    __ Cmp(Register(X23), Immediate(0));
13644514f5e3Sopenharmony_ci    __ B(Condition::EQ, &pushArgv);
13654514f5e3Sopenharmony_ci    __ Mov(tmpReg, currentSlotRegister);
13664514f5e3Sopenharmony_ci    __ Add(tmpReg, tmpReg, Immediate(AsmInterpretedFrame::GetSize(false)));
13674514f5e3Sopenharmony_ci    __ Add(Register(X9), frameStateBase, Immediate(AsmInterpretedFrame::GetBaseOffset(false)));
13684514f5e3Sopenharmony_ci    __ Str(tmpReg, MemoryOperand(Register(X9), InterpretedFrameBase::GetPrevOffset(false)));
13694514f5e3Sopenharmony_ci    __ Align16(currentSlotRegister);
13704514f5e3Sopenharmony_ci
13714514f5e3Sopenharmony_ci    __ Bind(&pushArgv);
13724514f5e3Sopenharmony_ci    __ Mov(tmpReg, outputCount);
13734514f5e3Sopenharmony_ci    __ Str(currentSlotRegister, MemoryOperand(frameStateBase, AsmInterpretedFrame::GetFpOffset(false)));
13744514f5e3Sopenharmony_ci    PushArgsWithArgv(assembler, glueRegister, outputCount, frameStateBase, opRegister,
13754514f5e3Sopenharmony_ci                     currentSlotRegister, nullptr, &stackOverflow);
13764514f5e3Sopenharmony_ci    __ Add(context, context, Immediate(FRAME_SLOT_SIZE)); // skip outputCount
13774514f5e3Sopenharmony_ci    __ Add(context, context, Operand(tmpReg, UXTW, FRAME_SLOT_SIZE_LOG2)); // skip args
13784514f5e3Sopenharmony_ci    __ Add(Register(X23), Register(X23), Immediate(1));
13794514f5e3Sopenharmony_ci    __ Cmp(depth, Register(X23));
13804514f5e3Sopenharmony_ci    __ B(Condition::GE, &loopBegin);
13814514f5e3Sopenharmony_ci
13824514f5e3Sopenharmony_ci    Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
13834514f5e3Sopenharmony_ci    Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD);
13844514f5e3Sopenharmony_ci    {
13854514f5e3Sopenharmony_ci        // X19, fp, x20, x21,      x22,     x23,  x24
13864514f5e3Sopenharmony_ci        // glue sp   pc  constpool  profile  acc   hotness
13874514f5e3Sopenharmony_ci        __ Ldr(callTargetRegister, MemoryOperand(frameStateBase, AsmInterpretedFrame::GetFunctionOffset(false)));
13884514f5e3Sopenharmony_ci        __ Ldr(Register(X20), MemoryOperand(frameStateBase, AsmInterpretedFrame::GetPcOffset(false)));
13894514f5e3Sopenharmony_ci        __ Ldr(Register(X23), MemoryOperand(frameStateBase, AsmInterpretedFrame::GetAccOffset(false)));
13904514f5e3Sopenharmony_ci        __ Ldr(methodRegister, MemoryOperand(callTargetRegister, JSFunctionBase::METHOD_OFFSET));
13914514f5e3Sopenharmony_ci
13924514f5e3Sopenharmony_ci        __ Add(opRegister, currentSlotRegister, Immediate(AsmInterpretedFrame::GetSize(false)));
13934514f5e3Sopenharmony_ci
13944514f5e3Sopenharmony_ci        __ Align16(currentSlotRegister);
13954514f5e3Sopenharmony_ci        __ Mov(Register(SP), currentSlotRegister);
13964514f5e3Sopenharmony_ci        AsmInterpreterCall::DispatchCall(assembler, Register(X20), opRegister, Register(X23));
13974514f5e3Sopenharmony_ci    }
13984514f5e3Sopenharmony_ci    __ Bind(&stackOverflow);
13994514f5e3Sopenharmony_ci    {
14004514f5e3Sopenharmony_ci        Register temp(X1);
14014514f5e3Sopenharmony_ci        AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(
14024514f5e3Sopenharmony_ci            assembler, glueRegister, sp, temp);
14034514f5e3Sopenharmony_ci    }
14044514f5e3Sopenharmony_ci}
14054514f5e3Sopenharmony_ci
14064514f5e3Sopenharmony_civoid OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
14074514f5e3Sopenharmony_ci{
14084514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(DeoptHandlerAsm));
14094514f5e3Sopenharmony_ci    __ PushFpAndLr();
14104514f5e3Sopenharmony_ci    Register sp(SP);
14114514f5e3Sopenharmony_ci    Register fp(FP);
14124514f5e3Sopenharmony_ci    Register frameType(X3);
14134514f5e3Sopenharmony_ci    Register glueReg(X0);
14144514f5e3Sopenharmony_ci
14154514f5e3Sopenharmony_ci    __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::ASM_BRIDGE_FRAME)));
14164514f5e3Sopenharmony_ci    __ Stp(glueReg, frameType, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
14174514f5e3Sopenharmony_ci    __ Add(fp, sp, Immediate(DOUBLE_SLOT_SIZE));
14184514f5e3Sopenharmony_ci    __ CalleeSave();
14194514f5e3Sopenharmony_ci
14204514f5e3Sopenharmony_ci    Register deoptType(X1);
14214514f5e3Sopenharmony_ci    Register depth(X2);
14224514f5e3Sopenharmony_ci    Register argC(X3);
14234514f5e3Sopenharmony_ci    Register runtimeId(X4);
14244514f5e3Sopenharmony_ci    __ Stp(deoptType, depth, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
14254514f5e3Sopenharmony_ci    __ Mov(argC, Immediate(2)); // 2: argc
14264514f5e3Sopenharmony_ci    __ Mov(runtimeId, Immediate(RTSTUB_ID(DeoptHandler)));
14274514f5e3Sopenharmony_ci    __ Stp(runtimeId, argC, MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
14284514f5e3Sopenharmony_ci    __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
14294514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(2 * DOUBLE_SLOT_SIZE)); // 2: skip runtimeId, argc, depth, shiftLen
14304514f5e3Sopenharmony_ci
14314514f5e3Sopenharmony_ci    __ CalleeRestore();
14324514f5e3Sopenharmony_ci    Register context(X2);
14334514f5e3Sopenharmony_ci    __ Mov(context, Register(X0));
14344514f5e3Sopenharmony_ci    __ Ldr(glueReg, MemoryOperand(sp, 0));
14354514f5e3Sopenharmony_ci
14364514f5e3Sopenharmony_ci    Register ret(X0);
14374514f5e3Sopenharmony_ci    Label stackOverflow;
14384514f5e3Sopenharmony_ci    __ Cmp(ret, Immediate(JSTaggedValue::VALUE_EXCEPTION));
14394514f5e3Sopenharmony_ci    __ B(Condition::EQ, &stackOverflow);
14404514f5e3Sopenharmony_ci
14414514f5e3Sopenharmony_ci    Label target;
14424514f5e3Sopenharmony_ci    Register temp(X1);
14434514f5e3Sopenharmony_ci    __ Ldr(fp, MemoryOperand(context, AsmStackContext::GetCallerFpOffset(false)));
14444514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(context, AsmStackContext::GetCallFrameTopOffset(false)));
14454514f5e3Sopenharmony_ci    __ Mov(sp, temp);
14464514f5e3Sopenharmony_ci    __ Ldr(Register(X30), MemoryOperand(context, AsmStackContext::GetReturnAddressOffset(false)));
14474514f5e3Sopenharmony_ci
14484514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
14494514f5e3Sopenharmony_ci    __ Bl(&target);
14504514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
14514514f5e3Sopenharmony_ci    __ Ret();
14524514f5e3Sopenharmony_ci    __ Bind(&target);
14534514f5e3Sopenharmony_ci    DeoptEnterAsmInterp(assembler);
14544514f5e3Sopenharmony_ci
14554514f5e3Sopenharmony_ci    __ Bind(&stackOverflow);
14564514f5e3Sopenharmony_ci    {
14574514f5e3Sopenharmony_ci        __ Mov(runtimeId, Immediate(RTSTUB_ID(ThrowStackOverflowException)));
14584514f5e3Sopenharmony_ci        // 2 : 2 means pair
14594514f5e3Sopenharmony_ci        __ Stp(runtimeId, Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
14604514f5e3Sopenharmony_ci        __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
14614514f5e3Sopenharmony_ci        __ Add(sp, sp, Immediate(2 * DOUBLE_SLOT_SIZE)); // 2: skip runtimeId&argc glue&type
14624514f5e3Sopenharmony_ci        __ RestoreFpAndLr();
14634514f5e3Sopenharmony_ci        __ Ret();
14644514f5e3Sopenharmony_ci    }
14654514f5e3Sopenharmony_ci}
14664514f5e3Sopenharmony_ci#undef __
14674514f5e3Sopenharmony_ci}  // panda::ecmascript::aarch64
1468