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, ©Arguments); 2474514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glue, tmp, undefinedValue, currentSp, nullptr, nullptr); 2484514f5e3Sopenharmony_ci } 2494514f5e3Sopenharmony_ci __ Bind(©Arguments); 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, ¬JSFunction); 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(¬JSFunction); 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, ©BoundArgument); 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(©BoundArgument); 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, ¬Class); 9884514f5e3Sopenharmony_ci __ Tbnz(hclass, JSHClass::ConstructorBit::START_BIT, &slowCall); 9894514f5e3Sopenharmony_ci __ Bind(¬Class); 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