14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023-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 OptimizedFastCallEntry(uintptr_t glue, uint32_t actualNumArgs, const JSTaggedType argV[], 354514f5e3Sopenharmony_ci// uintptr_t prevFp) 364514f5e3Sopenharmony_ci// * Arguments: 374514f5e3Sopenharmony_ci// %x0 - glue 384514f5e3Sopenharmony_ci// %x1 - actualNumArgs 394514f5e3Sopenharmony_ci// %x2 - argV 404514f5e3Sopenharmony_ci// %x3 - prevFp 414514f5e3Sopenharmony_civoid OptimizedFastCall::OptimizedFastCallEntry(ExtendedAssembler *assembler) 424514f5e3Sopenharmony_ci{ 434514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(OptimizedFastCallEntry)); 444514f5e3Sopenharmony_ci Register glueReg(X0); 454514f5e3Sopenharmony_ci Register argc(X1); 464514f5e3Sopenharmony_ci Register argV(X2); 474514f5e3Sopenharmony_ci Register prevFpReg(X3); 484514f5e3Sopenharmony_ci Register sp(SP); 494514f5e3Sopenharmony_ci 504514f5e3Sopenharmony_ci OptimizedCall::PushJSFunctionEntryFrame (assembler, prevFpReg); 514514f5e3Sopenharmony_ci __ Mov(Register(X3), argc); 524514f5e3Sopenharmony_ci __ Mov(Register(X4), argV); 534514f5e3Sopenharmony_ci Register tmpArgc(X3); 544514f5e3Sopenharmony_ci Register tmpArgV(X4); 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ci __ Mov(Register(X20), glueReg); 574514f5e3Sopenharmony_ci __ Ldr(Register(X1), MemoryOperand(tmpArgV, 0)); 584514f5e3Sopenharmony_ci __ Ldr(Register(X2), MemoryOperand(tmpArgV, FRAME_SLOT_SIZE)); 594514f5e3Sopenharmony_ci __ Add(tmpArgV, tmpArgV, Immediate(DOUBLE_SLOT_SIZE)); 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ci __ CallAssemblerStub(RTSTUB_ID(JSFastCallWithArgV), false); 624514f5e3Sopenharmony_ci __ Mov(Register(X2), Register(X20)); 634514f5e3Sopenharmony_ci OptimizedCall::PopJSFunctionEntryFrame(assembler, Register(X2)); 644514f5e3Sopenharmony_ci __ Ret(); 654514f5e3Sopenharmony_ci} 664514f5e3Sopenharmony_ci 674514f5e3Sopenharmony_ci// * uint64_t OptimizedFastCallAndPushArgv(uintptr_t glue, uint32_t expectedNumArgs, uint32_t actualNumArgs, 684514f5e3Sopenharmony_ci// uintptr_t codeAddr, uintptr_t argv) 694514f5e3Sopenharmony_ci// * Arguments wil CC calling convention: 704514f5e3Sopenharmony_ci// %x0 - glue 714514f5e3Sopenharmony_ci// %x1 - actualNumArgs 724514f5e3Sopenharmony_ci// %x2 - actualArgv 734514f5e3Sopenharmony_ci// %x3 - func 744514f5e3Sopenharmony_ci// %x4 - new target 754514f5e3Sopenharmony_ci// %x5 - this 764514f5e3Sopenharmony_ci// %x6 - arg0 774514f5e3Sopenharmony_ci// %x7 - arg1 784514f5e3Sopenharmony_ci// 794514f5e3Sopenharmony_ci// * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 804514f5e3Sopenharmony_ci// +--------------------------+ 814514f5e3Sopenharmony_ci// | arg[N-1] | 824514f5e3Sopenharmony_ci// +--------------------------+ 834514f5e3Sopenharmony_ci// | . . . . | 844514f5e3Sopenharmony_ci// +--------------------------+ 854514f5e3Sopenharmony_ci// | arg[0] | 864514f5e3Sopenharmony_ci// +--------------------------+ 874514f5e3Sopenharmony_ci// | argC | 884514f5e3Sopenharmony_ci// sp ---> +--------------------------+ ----------------- 894514f5e3Sopenharmony_ci// | | ^ 904514f5e3Sopenharmony_ci// | prevFP | | 914514f5e3Sopenharmony_ci// |--------------------------| OptimizedJSFunctionArgsConfigFrame 924514f5e3Sopenharmony_ci// | frameType | | 934514f5e3Sopenharmony_ci// | | V 944514f5e3Sopenharmony_ci// +--------------------------+ ----------------- 954514f5e3Sopenharmony_civoid OptimizedFastCall::OptimizedFastCallAndPushArgv(ExtendedAssembler *assembler) 964514f5e3Sopenharmony_ci{ 974514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(OptimizedFastCallAndPushArgv)); 984514f5e3Sopenharmony_ci Register glue(X0); 994514f5e3Sopenharmony_ci Register actualNumArgs(X1); 1004514f5e3Sopenharmony_ci Register actualArgv(X2); 1014514f5e3Sopenharmony_ci Register jsfunc(X3); 1024514f5e3Sopenharmony_ci Register codeAddr(X4); 1034514f5e3Sopenharmony_ci Register sp(SP); 1044514f5e3Sopenharmony_ci Register currentSp = __ AvailableRegister1(); 1054514f5e3Sopenharmony_ci Register op = __ AvailableRegister1(); 1064514f5e3Sopenharmony_ci Label call; 1074514f5e3Sopenharmony_ci Label arg4; 1084514f5e3Sopenharmony_ci Label arg5; 1094514f5e3Sopenharmony_ci Label arg6; 1104514f5e3Sopenharmony_ci Label argc; 1114514f5e3Sopenharmony_ci Label checkExpectedArgs; 1124514f5e3Sopenharmony_ci Label pushUndefined; 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_ci // construct frame 1154514f5e3Sopenharmony_ci OptimizedCall::PushOptimizedArgsConfigFrame(assembler); 1164514f5e3Sopenharmony_ci 1174514f5e3Sopenharmony_ci __ Mov(__ AvailableRegister3(), Register(X1)); 1184514f5e3Sopenharmony_ci __ Add(__ AvailableRegister4(), sp, Immediate(4 * FRAME_SLOT_SIZE)); // 4 skip fp lr type x19 1194514f5e3Sopenharmony_ci Register actualNumArgsReg = __ AvailableRegister3(); 1204514f5e3Sopenharmony_ci Register argV = __ AvailableRegister4(); 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ci Register method = __ AvailableRegister1(); 1234514f5e3Sopenharmony_ci Register expectedNumArgs = __ AvailableRegister2(); 1244514f5e3Sopenharmony_ci __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET)); 1254514f5e3Sopenharmony_ci __ Ldr(expectedNumArgs, MemoryOperand(method, Method::CALL_FIELD_OFFSET)); 1264514f5e3Sopenharmony_ci __ Lsr(expectedNumArgs, expectedNumArgs, MethodLiteral::NumArgsBits::START_BIT); 1274514f5e3Sopenharmony_ci __ And(expectedNumArgs, expectedNumArgs, 1284514f5e3Sopenharmony_ci LogicalImmediate::Create( 1294514f5e3Sopenharmony_ci MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegXSize)); 1304514f5e3Sopenharmony_ci __ Add(expectedNumArgs, expectedNumArgs, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); 1314514f5e3Sopenharmony_ci 1324514f5e3Sopenharmony_ci Label arg7; 1334514f5e3Sopenharmony_ci Label arg8; 1344514f5e3Sopenharmony_ci __ Mov(Register(X1), Register(X3)); // func move to argc 1354514f5e3Sopenharmony_ci __ Mov(Register(X2), Register(X5)); // this move to func 1364514f5e3Sopenharmony_ci jsfunc = Register(X1); 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(3)); // 3: 3 args 1394514f5e3Sopenharmony_ci __ B(Condition::NE, &arg4); 1404514f5e3Sopenharmony_ci __ Mov(Register(X3), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1414514f5e3Sopenharmony_ci __ Mov(Register(X4), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1424514f5e3Sopenharmony_ci __ Mov(Register(X5), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1434514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1444514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1454514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ci __ Bind(&arg4); 1484514f5e3Sopenharmony_ci { 1494514f5e3Sopenharmony_ci __ Mov(Register(X3), Register(X6)); 1504514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(4)); // 4: 4 args 1514514f5e3Sopenharmony_ci __ B(Condition::NE, &arg5); 1524514f5e3Sopenharmony_ci __ Mov(Register(X4), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1534514f5e3Sopenharmony_ci __ Mov(Register(X5), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1544514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1554514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1564514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 1574514f5e3Sopenharmony_ci } 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ci __ Bind(&arg5); 1604514f5e3Sopenharmony_ci { 1614514f5e3Sopenharmony_ci __ Mov(Register(X4), Register(X7)); 1624514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(5)); // 5: 5 args 1634514f5e3Sopenharmony_ci __ B(Condition::NE, &arg6); 1644514f5e3Sopenharmony_ci __ Mov(Register(X5), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1654514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1664514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1674514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci 1704514f5e3Sopenharmony_ci __ Bind(&arg6); 1714514f5e3Sopenharmony_ci { 1724514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 1734514f5e3Sopenharmony_ci __ Mov(Register(X5), op); 1744514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 1754514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(6)); // 6: 6 args 1764514f5e3Sopenharmony_ci __ B(Condition::NE, &arg7); 1774514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1784514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1794514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 1804514f5e3Sopenharmony_ci } 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ci __ Bind(&arg7); 1834514f5e3Sopenharmony_ci { 1844514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 1854514f5e3Sopenharmony_ci __ Mov(Register(X6), op); 1864514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 1874514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(7)); // 7: 7 args 1884514f5e3Sopenharmony_ci __ B(Condition::NE, &arg8); 1894514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 1904514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 1914514f5e3Sopenharmony_ci } 1924514f5e3Sopenharmony_ci 1934514f5e3Sopenharmony_ci __ Bind(&arg8); 1944514f5e3Sopenharmony_ci { 1954514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 1964514f5e3Sopenharmony_ci __ Mov(Register(X7), op); 1974514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 1984514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(8)); // 8: 8 args 1994514f5e3Sopenharmony_ci __ B(Condition::NE, &argc); 2004514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 2014514f5e3Sopenharmony_ci } 2024514f5e3Sopenharmony_ci 2034514f5e3Sopenharmony_ci __ Bind(&argc); 2044514f5e3Sopenharmony_ci { 2054514f5e3Sopenharmony_ci TempRegister1Scope scope1(assembler); 2064514f5e3Sopenharmony_ci TempRegister2Scope scope2(assembler); 2074514f5e3Sopenharmony_ci Register tmp = __ TempRegister1(); 2084514f5e3Sopenharmony_ci Register undefinedValue = __ TempRegister2(); 2094514f5e3Sopenharmony_ci 2104514f5e3Sopenharmony_ci __ Cmp(expectedNumArgs, actualNumArgsReg); 2114514f5e3Sopenharmony_ci __ B(Condition::GT, &pushUndefined); 2124514f5e3Sopenharmony_ci __ Sub(expectedNumArgs, expectedNumArgs, Immediate(8)); // 8 : register save 8 arg 2134514f5e3Sopenharmony_ci __ Sub(actualNumArgsReg, actualNumArgsReg, Immediate(8)); // 8 : register save 8 arg 2144514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, actualNumArgsReg, currentSp); 2154514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, actualNumArgsReg, argV, undefinedValue, currentSp, nullptr, nullptr); 2164514f5e3Sopenharmony_ci __ B(&call); 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ci __ Bind(&pushUndefined); 2194514f5e3Sopenharmony_ci __ Sub(expectedNumArgs, expectedNumArgs, Immediate(8)); // 8 : register save 8 arg 2204514f5e3Sopenharmony_ci __ Sub(actualNumArgsReg, actualNumArgsReg, Immediate(8)); // 8 : register save 8 arg 2214514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, expectedNumArgs, currentSp); 2224514f5e3Sopenharmony_ci __ Sub(tmp, expectedNumArgs, actualNumArgsReg); 2234514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glue, tmp, undefinedValue, currentSp, nullptr, nullptr); 2244514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, actualNumArgsReg, argV, undefinedValue, currentSp, nullptr, nullptr); 2254514f5e3Sopenharmony_ci __ B(&call); 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci 2284514f5e3Sopenharmony_ci __ Bind(&checkExpectedArgs); 2294514f5e3Sopenharmony_ci { 2304514f5e3Sopenharmony_ci __ Cmp(expectedNumArgs, Immediate(8)); // 8 : register save 8 arg 2314514f5e3Sopenharmony_ci __ B(Condition::LS, &call); 2324514f5e3Sopenharmony_ci __ Sub(expectedNumArgs, expectedNumArgs, Immediate(8)); // 8 : register save 8 arg 2334514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, expectedNumArgs, currentSp); 2344514f5e3Sopenharmony_ci TempRegister2Scope scope2(assembler); 2354514f5e3Sopenharmony_ci Register undefinedValue = __ TempRegister2(); 2364514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glue, expectedNumArgs, undefinedValue, currentSp, nullptr, nullptr); 2374514f5e3Sopenharmony_ci __ B(&call); 2384514f5e3Sopenharmony_ci } 2394514f5e3Sopenharmony_ci __ Bind(&call); 2404514f5e3Sopenharmony_ci TempRegister1Scope scope1(assembler); 2414514f5e3Sopenharmony_ci Register method1 = __ TempRegister1(); 2424514f5e3Sopenharmony_ci __ Ldr(method1, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET)); 2434514f5e3Sopenharmony_ci __ Ldr(X11, MemoryOperand(jsfunc, JSFunction::CODE_ENTRY_OFFSET)); 2444514f5e3Sopenharmony_ci __ Blr(X11); 2454514f5e3Sopenharmony_ci 2464514f5e3Sopenharmony_ci __ Mov(Register(SP), Register(FP)); 2474514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 2484514f5e3Sopenharmony_ci __ Ret(); 2494514f5e3Sopenharmony_ci} 2504514f5e3Sopenharmony_ci 2514514f5e3Sopenharmony_ci// * uint64_t JSFastCallWithArgV(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, 2524514f5e3Sopenharmony_ci// JSTaggedType this, argV) 2534514f5e3Sopenharmony_ci// * cc calling convention call js function() 2544514f5e3Sopenharmony_ci// * arguments: 2554514f5e3Sopenharmony_ci// %x0 - glue 2564514f5e3Sopenharmony_ci// %x1 - call-target 2574514f5e3Sopenharmony_ci// %x2 - this 2584514f5e3Sopenharmony_ci// %x3 - artual argc 2594514f5e3Sopenharmony_ci// %x4 - argv 2604514f5e3Sopenharmony_civoid OptimizedFastCall::JSFastCallWithArgV(ExtendedAssembler *assembler) 2614514f5e3Sopenharmony_ci{ 2624514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(JSFastCallWithArgV)); 2634514f5e3Sopenharmony_ci Register sp(SP); 2644514f5e3Sopenharmony_ci Register glue(X0); 2654514f5e3Sopenharmony_ci Register actualNumArgs(X3); 2664514f5e3Sopenharmony_ci Register jsfunc(X1); 2674514f5e3Sopenharmony_ci Register thisObj(X2); 2684514f5e3Sopenharmony_ci Register currentSp = __ AvailableRegister1(); 2694514f5e3Sopenharmony_ci Register callsiteSp = __ AvailableRegister2(); 2704514f5e3Sopenharmony_ci Label call; 2714514f5e3Sopenharmony_ci __ Mov(callsiteSp, sp); 2724514f5e3Sopenharmony_ci OptimizedCall::PushOptimizedUnfoldArgVFrame(assembler, callsiteSp); 2734514f5e3Sopenharmony_ci TempRegister2Scope scope2(assembler); 2744514f5e3Sopenharmony_ci Register op = __ TempRegister2(); 2754514f5e3Sopenharmony_ci Register argC = __ AvailableRegister3(); 2764514f5e3Sopenharmony_ci Register argV = __ AvailableRegister4(); 2774514f5e3Sopenharmony_ci __ Mov(argC, actualNumArgs); 2784514f5e3Sopenharmony_ci __ Mov(argV, Register(X4)); 2794514f5e3Sopenharmony_ci 2804514f5e3Sopenharmony_ci __ Cmp(argC, Immediate(0)); 2814514f5e3Sopenharmony_ci __ B(Condition::EQ, &call); 2824514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 2834514f5e3Sopenharmony_ci __ Mov(Register(X3), op); // first arg 2844514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 2854514f5e3Sopenharmony_ci __ Sub(argC, argC, Immediate(1)); 2864514f5e3Sopenharmony_ci 2874514f5e3Sopenharmony_ci __ Cmp(argC, Immediate(0)); 2884514f5e3Sopenharmony_ci __ B(Condition::EQ, &call); 2894514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 2904514f5e3Sopenharmony_ci __ Mov(Register(X4), op); // second arg 2914514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 2924514f5e3Sopenharmony_ci __ Sub(argC, argC, Immediate(1)); 2934514f5e3Sopenharmony_ci 2944514f5e3Sopenharmony_ci __ Cmp(argC, Immediate(0)); 2954514f5e3Sopenharmony_ci __ B(Condition::EQ, &call); 2964514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 2974514f5e3Sopenharmony_ci __ Mov(Register(X5), op); // third arg 2984514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 2994514f5e3Sopenharmony_ci __ Sub(argC, argC, Immediate(1)); 3004514f5e3Sopenharmony_ci 3014514f5e3Sopenharmony_ci __ Cmp(argC, Immediate(0)); 3024514f5e3Sopenharmony_ci __ B(Condition::EQ, &call); 3034514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 3044514f5e3Sopenharmony_ci __ Mov(Register(X6), op); 3054514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 3064514f5e3Sopenharmony_ci __ Sub(argC, argC, Immediate(1)); 3074514f5e3Sopenharmony_ci 3084514f5e3Sopenharmony_ci __ Cmp(argC, Immediate(0)); 3094514f5e3Sopenharmony_ci __ B(Condition::EQ, &call); 3104514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 3114514f5e3Sopenharmony_ci __ Mov(Register(X7), op); 3124514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 3134514f5e3Sopenharmony_ci __ Sub(argC, argC, Immediate(1)); 3144514f5e3Sopenharmony_ci 3154514f5e3Sopenharmony_ci __ Cmp(argC, Immediate(0)); 3164514f5e3Sopenharmony_ci __ B(Condition::EQ, &call); 3174514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, argC, currentSp); 3184514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, argC, argV, op, currentSp, nullptr, nullptr); 3194514f5e3Sopenharmony_ci 3204514f5e3Sopenharmony_ci __ Bind(&call); 3214514f5e3Sopenharmony_ci TempRegister1Scope scope1(assembler); 3224514f5e3Sopenharmony_ci Register method = __ TempRegister1(); 3234514f5e3Sopenharmony_ci __ Ldr(method, MemoryOperand(jsfunc, JSFunction::METHOD_OFFSET)); 3244514f5e3Sopenharmony_ci __ Ldr(X11, MemoryOperand(jsfunc, JSFunctionBase::CODE_ENTRY_OFFSET)); 3254514f5e3Sopenharmony_ci __ Blr(X11); 3264514f5e3Sopenharmony_ci 3274514f5e3Sopenharmony_ci __ Mov(Register(SP), Register(FP)); 3284514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 3294514f5e3Sopenharmony_ci __ Ret(); 3304514f5e3Sopenharmony_ci} 3314514f5e3Sopenharmony_ci 3324514f5e3Sopenharmony_ci// * Arguments: 3334514f5e3Sopenharmony_ci// %x0 - glue 3344514f5e3Sopenharmony_ci// %x1 - func 3354514f5e3Sopenharmony_ci// %x2 - this 3364514f5e3Sopenharmony_ci// %x3 - actualNumArgs 3374514f5e3Sopenharmony_ci// %x4 - argv 3384514f5e3Sopenharmony_ci// %x5 - expectedNumArgs 3394514f5e3Sopenharmony_civoid OptimizedFastCall::JSFastCallWithArgVAndPushArgv(ExtendedAssembler *assembler) 3404514f5e3Sopenharmony_ci{ 3414514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(JSFastCallWithArgVAndPushArgv)); 3424514f5e3Sopenharmony_ci Register sp(SP); 3434514f5e3Sopenharmony_ci Register glue(X0); 3444514f5e3Sopenharmony_ci Register jsfunc(X1); 3454514f5e3Sopenharmony_ci Register thisObj(X2); 3464514f5e3Sopenharmony_ci Register currentSp = __ AvailableRegister1(); 3474514f5e3Sopenharmony_ci Register op = __ AvailableRegister1(); 3484514f5e3Sopenharmony_ci Register callsiteSp = __ AvailableRegister2(); 3494514f5e3Sopenharmony_ci Label call; 3504514f5e3Sopenharmony_ci Label arg1; 3514514f5e3Sopenharmony_ci Label arg2; 3524514f5e3Sopenharmony_ci Label arg3; 3534514f5e3Sopenharmony_ci Label arg4; 3544514f5e3Sopenharmony_ci Label arg5; 3554514f5e3Sopenharmony_ci Label argc; 3564514f5e3Sopenharmony_ci Label checkExpectedArgs; 3574514f5e3Sopenharmony_ci Label pushUndefined; 3584514f5e3Sopenharmony_ci __ Mov(callsiteSp, sp); 3594514f5e3Sopenharmony_ci OptimizedCall::PushOptimizedUnfoldArgVFrame(assembler, callsiteSp); 3604514f5e3Sopenharmony_ci Register actualNumArgsReg = __ AvailableRegister3(); 3614514f5e3Sopenharmony_ci Register argV = __ AvailableRegister4(); 3624514f5e3Sopenharmony_ci Register expectedNumArgs = __ AvailableRegister2(); 3634514f5e3Sopenharmony_ci __ Mov(actualNumArgsReg, Register(X3)); 3644514f5e3Sopenharmony_ci __ Mov(argV, Register(X4)); 3654514f5e3Sopenharmony_ci __ Mov(expectedNumArgs, Register(X5)); 3664514f5e3Sopenharmony_ci 3674514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(0)); 3684514f5e3Sopenharmony_ci __ B(Condition::NE, &arg1); 3694514f5e3Sopenharmony_ci __ Mov(Register(X3), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3704514f5e3Sopenharmony_ci __ Mov(Register(X4), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3714514f5e3Sopenharmony_ci __ Mov(Register(X5), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3724514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3734514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3744514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 3754514f5e3Sopenharmony_ci 3764514f5e3Sopenharmony_ci __ Bind(&arg1); 3774514f5e3Sopenharmony_ci { 3784514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 3794514f5e3Sopenharmony_ci __ Mov(Register(X3), op); 3804514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 3814514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(1)); 3824514f5e3Sopenharmony_ci __ B(Condition::NE, &arg2); 3834514f5e3Sopenharmony_ci __ Mov(Register(X4), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3844514f5e3Sopenharmony_ci __ Mov(Register(X5), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3854514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3864514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3874514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 3884514f5e3Sopenharmony_ci } 3894514f5e3Sopenharmony_ci 3904514f5e3Sopenharmony_ci __ Bind(&arg2); 3914514f5e3Sopenharmony_ci { 3924514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 3934514f5e3Sopenharmony_ci __ Mov(Register(X4), op); 3944514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 3954514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(2)); // 2: 2 args 3964514f5e3Sopenharmony_ci __ B(Condition::NE, &arg3); 3974514f5e3Sopenharmony_ci __ Mov(Register(X5), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3984514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 3994514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 4004514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 4014514f5e3Sopenharmony_ci } 4024514f5e3Sopenharmony_ci 4034514f5e3Sopenharmony_ci __ Bind(&arg3); 4044514f5e3Sopenharmony_ci { 4054514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 4064514f5e3Sopenharmony_ci __ Mov(Register(X5), op); 4074514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 4084514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(3)); // 3: 3 args 4094514f5e3Sopenharmony_ci __ B(Condition::NE, &arg4); 4104514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 4114514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 4124514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 4134514f5e3Sopenharmony_ci } 4144514f5e3Sopenharmony_ci 4154514f5e3Sopenharmony_ci __ Bind(&arg4); 4164514f5e3Sopenharmony_ci { 4174514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 4184514f5e3Sopenharmony_ci __ Mov(Register(X6), op); 4194514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 4204514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(4)); // 4: 4 args 4214514f5e3Sopenharmony_ci __ B(Condition::NE, &arg5); 4224514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 4234514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 4244514f5e3Sopenharmony_ci } 4254514f5e3Sopenharmony_ci 4264514f5e3Sopenharmony_ci __ Bind(&arg5); 4274514f5e3Sopenharmony_ci { 4284514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(argV, 0)); 4294514f5e3Sopenharmony_ci __ Mov(Register(X7), op); 4304514f5e3Sopenharmony_ci __ Add(argV, argV, Immediate(FRAME_SLOT_SIZE)); 4314514f5e3Sopenharmony_ci __ Cmp(actualNumArgsReg, Immediate(5)); // 5: 5 args 4324514f5e3Sopenharmony_ci __ B(Condition::NE, &argc); 4334514f5e3Sopenharmony_ci __ B(&checkExpectedArgs); 4344514f5e3Sopenharmony_ci } 4354514f5e3Sopenharmony_ci 4364514f5e3Sopenharmony_ci __ Bind(&argc); 4374514f5e3Sopenharmony_ci { 4384514f5e3Sopenharmony_ci TempRegister1Scope scope1(assembler); 4394514f5e3Sopenharmony_ci TempRegister2Scope scope2(assembler); 4404514f5e3Sopenharmony_ci Register tmp = __ TempRegister1(); 4414514f5e3Sopenharmony_ci Register undefinedValue = __ TempRegister2(); 4424514f5e3Sopenharmony_ci 4434514f5e3Sopenharmony_ci __ Cmp(expectedNumArgs, actualNumArgsReg); 4444514f5e3Sopenharmony_ci __ B(Condition::GT, &pushUndefined); 4454514f5e3Sopenharmony_ci __ Sub(expectedNumArgs, expectedNumArgs, Immediate(5)); // 5 : register save 5 arg 4464514f5e3Sopenharmony_ci __ Sub(actualNumArgsReg, actualNumArgsReg, Immediate(5)); // 5 : register save 5 arg 4474514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, actualNumArgsReg, currentSp); 4484514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, actualNumArgsReg, argV, undefinedValue, currentSp, nullptr, nullptr); 4494514f5e3Sopenharmony_ci __ B(&call); 4504514f5e3Sopenharmony_ci 4514514f5e3Sopenharmony_ci __ Bind(&pushUndefined); 4524514f5e3Sopenharmony_ci __ Sub(expectedNumArgs, expectedNumArgs, Immediate(5)); // 5 : register save 5 arg 4534514f5e3Sopenharmony_ci __ Sub(actualNumArgsReg, actualNumArgsReg, Immediate(5)); // 5 : register save 5 arg 4544514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, expectedNumArgs, currentSp); 4554514f5e3Sopenharmony_ci __ Sub(tmp, expectedNumArgs, actualNumArgsReg); 4564514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glue, tmp, undefinedValue, currentSp, nullptr, nullptr); 4574514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, actualNumArgsReg, argV, undefinedValue, currentSp, nullptr, nullptr); 4584514f5e3Sopenharmony_ci __ B(&call); 4594514f5e3Sopenharmony_ci } 4604514f5e3Sopenharmony_ci 4614514f5e3Sopenharmony_ci __ Bind(&checkExpectedArgs); 4624514f5e3Sopenharmony_ci { 4634514f5e3Sopenharmony_ci __ Cmp(expectedNumArgs, Immediate(5)); // 5 : register save 5 arg 4644514f5e3Sopenharmony_ci __ B(Condition::LS, &call); 4654514f5e3Sopenharmony_ci __ Sub(expectedNumArgs, expectedNumArgs, Immediate(5)); // 5 : register save 5 arg 4664514f5e3Sopenharmony_ci OptimizedCall::IncreaseStackForArguments(assembler, expectedNumArgs, currentSp); 4674514f5e3Sopenharmony_ci TempRegister2Scope scope2(assembler); 4684514f5e3Sopenharmony_ci Register undefinedValue = __ TempRegister2(); 4694514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glue, expectedNumArgs, undefinedValue, currentSp, nullptr, nullptr); 4704514f5e3Sopenharmony_ci __ B(&call); 4714514f5e3Sopenharmony_ci } 4724514f5e3Sopenharmony_ci 4734514f5e3Sopenharmony_ci __ Bind(&call); 4744514f5e3Sopenharmony_ci TempRegister1Scope scope1(assembler); 4754514f5e3Sopenharmony_ci Register method = __ TempRegister1(); 4764514f5e3Sopenharmony_ci __ Ldr(method, MemoryOperand(X1, JSFunction::METHOD_OFFSET)); 4774514f5e3Sopenharmony_ci __ Ldr(X11, MemoryOperand(X1, JSFunction::CODE_ENTRY_OFFSET)); 4784514f5e3Sopenharmony_ci __ Blr(X11); 4794514f5e3Sopenharmony_ci 4804514f5e3Sopenharmony_ci __ Mov(Register(SP), Register(FP)); 4814514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 4824514f5e3Sopenharmony_ci __ Ret(); 4834514f5e3Sopenharmony_ci} 4844514f5e3Sopenharmony_ci#undef __ 4854514f5e3Sopenharmony_ci} // panda::ecmascript::aarch64