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/ecma_runtime_call_info.h" 224514f5e3Sopenharmony_ci#include "ecmascript/frames.h" 234514f5e3Sopenharmony_ci#include "ecmascript/js_function.h" 244514f5e3Sopenharmony_ci#include "ecmascript/mem/machine_code.h" 254514f5e3Sopenharmony_ci#include "ecmascript/method.h" 264514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h" 274514f5e3Sopenharmony_ci#include "ecmascript/js_generator_object.h" 284514f5e3Sopenharmony_ci#include "ecmascript/message_string.h" 294514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h" 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_cinamespace panda::ecmascript::aarch64 { 324514f5e3Sopenharmony_ciusing Label = panda::ecmascript::Label; 334514f5e3Sopenharmony_ci#define __ assembler-> 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_ci// Generate code for entering asm interpreter 364514f5e3Sopenharmony_ci// c++ calling convention 374514f5e3Sopenharmony_ci// Input: glue - %X0 384514f5e3Sopenharmony_ci// callTarget - %X1 394514f5e3Sopenharmony_ci// method - %X2 404514f5e3Sopenharmony_ci// callField - %X3 414514f5e3Sopenharmony_ci// argc - %X4 424514f5e3Sopenharmony_ci// argv - %X5(<callTarget, newTarget, this> are at the beginning of argv) 434514f5e3Sopenharmony_civoid AsmInterpreterCall::AsmInterpreterEntry(ExtendedAssembler *assembler) 444514f5e3Sopenharmony_ci{ 454514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(AsmInterpreterEntry)); 464514f5e3Sopenharmony_ci Label target; 474514f5e3Sopenharmony_ci size_t begin = __ GetCurrentPosition(); 484514f5e3Sopenharmony_ci PushAsmInterpEntryFrame(assembler); 494514f5e3Sopenharmony_ci __ Bl(&target); 504514f5e3Sopenharmony_ci PopAsmInterpEntryFrame(assembler); 514514f5e3Sopenharmony_ci size_t end = __ GetCurrentPosition(); 524514f5e3Sopenharmony_ci if ((end - begin) != FrameCompletionPos::ARM64EntryFrameDuration) { 534514f5e3Sopenharmony_ci LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64EntryFrameDuration 544514f5e3Sopenharmony_ci << "This frame has been modified, and the offset EntryFrameDuration should be updated too."; 554514f5e3Sopenharmony_ci } 564514f5e3Sopenharmony_ci __ Ret(); 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_ci __ Bind(&target); 594514f5e3Sopenharmony_ci { 604514f5e3Sopenharmony_ci AsmInterpEntryDispatch(assembler); 614514f5e3Sopenharmony_ci } 624514f5e3Sopenharmony_ci} 634514f5e3Sopenharmony_ci 644514f5e3Sopenharmony_ci// Input: glue - %X0 654514f5e3Sopenharmony_ci// callTarget - %X1 664514f5e3Sopenharmony_ci// method - %X2 674514f5e3Sopenharmony_ci// callField - %X3 684514f5e3Sopenharmony_ci// argc - %X4 694514f5e3Sopenharmony_ci// argv - %X5(<callTarget, newTarget, this> are at the beginning of argv) 704514f5e3Sopenharmony_civoid AsmInterpreterCall::AsmInterpEntryDispatch(ExtendedAssembler *assembler) 714514f5e3Sopenharmony_ci{ 724514f5e3Sopenharmony_ci Label notJSFunction; 734514f5e3Sopenharmony_ci Label callNativeEntry; 744514f5e3Sopenharmony_ci Label callJSFunctionEntry; 754514f5e3Sopenharmony_ci Label notCallable; 764514f5e3Sopenharmony_ci Register glueRegister(X0); 774514f5e3Sopenharmony_ci Register argcRegister(X4, W); 784514f5e3Sopenharmony_ci Register argvRegister(X5); 794514f5e3Sopenharmony_ci Register callTargetRegister(X1); 804514f5e3Sopenharmony_ci Register callFieldRegister(X3); 814514f5e3Sopenharmony_ci Register bitFieldRegister(X16); 824514f5e3Sopenharmony_ci Register tempRegister(X17); // can not be used to store any variable 834514f5e3Sopenharmony_ci Register functionTypeRegister(X18, W); 844514f5e3Sopenharmony_ci __ Ldr(tempRegister, MemoryOperand(callTargetRegister, TaggedObject::HCLASS_OFFSET)); 854514f5e3Sopenharmony_ci __ Ldr(bitFieldRegister, MemoryOperand(tempRegister, JSHClass::BIT_FIELD_OFFSET)); 864514f5e3Sopenharmony_ci __ And(functionTypeRegister, bitFieldRegister.W(), LogicalImmediate::Create(0xFF, RegWSize)); 874514f5e3Sopenharmony_ci __ Mov(tempRegister.W(), Immediate(static_cast<int64_t>(JSType::JS_FUNCTION_FIRST))); 884514f5e3Sopenharmony_ci __ Cmp(functionTypeRegister, tempRegister.W()); 894514f5e3Sopenharmony_ci __ B(Condition::LO, ¬JSFunction); 904514f5e3Sopenharmony_ci __ Mov(tempRegister.W(), Immediate(static_cast<int64_t>(JSType::JS_FUNCTION_LAST))); 914514f5e3Sopenharmony_ci __ Cmp(functionTypeRegister, tempRegister.W()); 924514f5e3Sopenharmony_ci __ B(Condition::LS, &callJSFunctionEntry); 934514f5e3Sopenharmony_ci __ Bind(¬JSFunction); 944514f5e3Sopenharmony_ci { 954514f5e3Sopenharmony_ci __ Tst(bitFieldRegister, 964514f5e3Sopenharmony_ci LogicalImmediate::Create(static_cast<int64_t>(1ULL << JSHClass::CallableBit::START_BIT), RegXSize)); 974514f5e3Sopenharmony_ci __ B(Condition::EQ, ¬Callable); 984514f5e3Sopenharmony_ci // fall through 994514f5e3Sopenharmony_ci } 1004514f5e3Sopenharmony_ci __ Bind(&callNativeEntry); 1014514f5e3Sopenharmony_ci CallNativeEntry(assembler); 1024514f5e3Sopenharmony_ci __ Bind(&callJSFunctionEntry); 1034514f5e3Sopenharmony_ci { 1044514f5e3Sopenharmony_ci __ Tbnz(callFieldRegister, MethodLiteral::IsNativeBit::START_BIT, &callNativeEntry); 1054514f5e3Sopenharmony_ci // fast path 1064514f5e3Sopenharmony_ci __ Add(argvRegister, argvRegister, Immediate(NUM_MANDATORY_JSFUNC_ARGS * JSTaggedValue::TaggedTypeSize())); 1074514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_ENTRY, FrameTransitionType::OTHER_TO_BASELINE_CHECK); 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci __ Bind(¬Callable); 1104514f5e3Sopenharmony_ci { 1114514f5e3Sopenharmony_ci Register runtimeId(X11); 1124514f5e3Sopenharmony_ci Register trampoline(X12); 1134514f5e3Sopenharmony_ci __ Mov(runtimeId, Immediate(kungfu::RuntimeStubCSigns::ID_ThrowNotCallableException)); 1144514f5e3Sopenharmony_ci // 3 : 3 means *8 1154514f5e3Sopenharmony_ci __ Add(trampoline, glueRegister, Operand(runtimeId, LSL, 3)); 1164514f5e3Sopenharmony_ci __ Ldr(trampoline, MemoryOperand(trampoline, JSThread::GlueData::GetRTStubEntriesOffset(false))); 1174514f5e3Sopenharmony_ci __ Blr(trampoline); 1184514f5e3Sopenharmony_ci __ Ret(); 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci} 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_civoid AsmInterpreterCall::JSCallCommonEntry(ExtendedAssembler *assembler, 1234514f5e3Sopenharmony_ci JSCallMode mode, FrameTransitionType type) 1244514f5e3Sopenharmony_ci{ 1254514f5e3Sopenharmony_ci Label stackOverflow; 1264514f5e3Sopenharmony_ci Register glueRegister = __ GlueRegister(); 1274514f5e3Sopenharmony_ci Register fpRegister = __ AvailableRegister1(); 1284514f5e3Sopenharmony_ci Register currentSlotRegister = __ AvailableRegister3(); 1294514f5e3Sopenharmony_ci Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); 1304514f5e3Sopenharmony_ci Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); 1314514f5e3Sopenharmony_ci if (!kungfu::AssemblerModule::IsJumpToCallCommonEntry(mode) || type == FrameTransitionType::BASELINE_TO_OTHER || 1324514f5e3Sopenharmony_ci type == FrameTransitionType::BASELINE_TO_BASELINE_CHECK) { 1334514f5e3Sopenharmony_ci __ PushFpAndLr(); 1344514f5e3Sopenharmony_ci } 1354514f5e3Sopenharmony_ci // save fp 1364514f5e3Sopenharmony_ci __ Mov(fpRegister, Register(SP)); 1374514f5e3Sopenharmony_ci __ Mov(currentSlotRegister, Register(SP)); 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci { 1404514f5e3Sopenharmony_ci // Reserve enough sp space to prevent stack parameters from being covered by cpu profiler. 1414514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope(assembler); 1424514f5e3Sopenharmony_ci Register tempRegister = __ TempRegister1(); 1434514f5e3Sopenharmony_ci __ Ldr(tempRegister, MemoryOperand(glueRegister, JSThread::GlueData::GetStackLimitOffset(false))); 1444514f5e3Sopenharmony_ci __ Mov(Register(SP), tempRegister); 1454514f5e3Sopenharmony_ci } 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ci Register declaredNumArgsRegister = __ AvailableRegister2(); 1484514f5e3Sopenharmony_ci GetDeclaredNumArgsFromCallField(assembler, callFieldRegister, declaredNumArgsRegister); 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ci Label slowPathEntry; 1514514f5e3Sopenharmony_ci Label fastPathEntry; 1524514f5e3Sopenharmony_ci Label pushCallThis; 1534514f5e3Sopenharmony_ci auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode); 1544514f5e3Sopenharmony_ci if (argc >= 0) { 1554514f5e3Sopenharmony_ci __ Cmp(declaredNumArgsRegister, Immediate(argc)); 1564514f5e3Sopenharmony_ci } else { 1574514f5e3Sopenharmony_ci __ Cmp(declaredNumArgsRegister, argcRegister); 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci __ B(Condition::NE, &slowPathEntry); 1604514f5e3Sopenharmony_ci __ Bind(&fastPathEntry); 1614514f5e3Sopenharmony_ci JSCallCommonFastPath(assembler, mode, &pushCallThis, &stackOverflow); 1624514f5e3Sopenharmony_ci __ Bind(&pushCallThis); 1634514f5e3Sopenharmony_ci PushCallThis(assembler, mode, &stackOverflow, type); 1644514f5e3Sopenharmony_ci __ Bind(&slowPathEntry); 1654514f5e3Sopenharmony_ci JSCallCommonSlowPath(assembler, mode, &fastPathEntry, &pushCallThis, &stackOverflow); 1664514f5e3Sopenharmony_ci 1674514f5e3Sopenharmony_ci __ Bind(&stackOverflow); 1684514f5e3Sopenharmony_ci if (kungfu::AssemblerModule::IsJumpToCallCommonEntry(mode)) { 1694514f5e3Sopenharmony_ci __ Mov(Register(SP), fpRegister); 1704514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope(assembler); 1714514f5e3Sopenharmony_ci Register temp = __ TempRegister1(); 1724514f5e3Sopenharmony_ci // only glue and acc are useful in exception handler 1734514f5e3Sopenharmony_ci if (glueRegister.GetId() != X19) { 1744514f5e3Sopenharmony_ci __ Mov(Register(X19), glueRegister); 1754514f5e3Sopenharmony_ci } 1764514f5e3Sopenharmony_ci Register acc(X23); 1774514f5e3Sopenharmony_ci __ Mov(acc, Immediate(JSTaggedValue::VALUE_EXCEPTION)); 1784514f5e3Sopenharmony_ci Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD); 1794514f5e3Sopenharmony_ci Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); 1804514f5e3Sopenharmony_ci // Reload pc to make sure stack trace is right 1814514f5e3Sopenharmony_ci __ Mov(temp, callTargetRegister); 1824514f5e3Sopenharmony_ci __ Ldr(Register(X20), MemoryOperand(methodRegister, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)); 1834514f5e3Sopenharmony_ci // Reload constpool and profileInfo to make sure gc map work normally 1844514f5e3Sopenharmony_ci __ Ldr(Register(X22), MemoryOperand(temp, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET)); 1854514f5e3Sopenharmony_ci __ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET)); 1864514f5e3Sopenharmony_ci __ Ldr(Register(X21), MemoryOperand(methodRegister, Method::CONSTANT_POOL_OFFSET)); 1874514f5e3Sopenharmony_ci 1884514f5e3Sopenharmony_ci __ Mov(temp, kungfu::BytecodeStubCSigns::ID_ThrowStackOverflowException); 1894514f5e3Sopenharmony_ci __ Add(temp, glueRegister, Operand(temp, UXTW, 3)); // 3: bc * 8 1904514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, JSThread::GlueData::GetBCStubEntriesOffset(false))); 1914514f5e3Sopenharmony_ci __ Br(temp); 1924514f5e3Sopenharmony_ci } else { 1934514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope(assembler); 1944514f5e3Sopenharmony_ci Register temp = __ TempRegister1(); 1954514f5e3Sopenharmony_ci ThrowStackOverflowExceptionAndReturn(assembler, glueRegister, fpRegister, temp); 1964514f5e3Sopenharmony_ci } 1974514f5e3Sopenharmony_ci} 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_civoid AsmInterpreterCall::JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis, 2004514f5e3Sopenharmony_ci Label *stackOverflow) 2014514f5e3Sopenharmony_ci{ 2024514f5e3Sopenharmony_ci Register glueRegister = __ GlueRegister(); 2034514f5e3Sopenharmony_ci auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode); 2044514f5e3Sopenharmony_ci Register currentSlotRegister = __ AvailableRegister3(); 2054514f5e3Sopenharmony_ci // call range 2064514f5e3Sopenharmony_ci if (argc < 0) { 2074514f5e3Sopenharmony_ci Register numRegister = __ AvailableRegister2(); 2084514f5e3Sopenharmony_ci Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); 2094514f5e3Sopenharmony_ci Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV); 2104514f5e3Sopenharmony_ci __ Mov(numRegister, argcRegister); 2114514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope(assembler); 2124514f5e3Sopenharmony_ci Register opRegister = __ TempRegister1(); 2134514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glueRegister, numRegister, argvRegister, opRegister, 2144514f5e3Sopenharmony_ci currentSlotRegister, pushCallThis, stackOverflow); 2154514f5e3Sopenharmony_ci } else if (argc > 0) { 2164514f5e3Sopenharmony_ci if (argc > 2) { // 2: call arg2 2174514f5e3Sopenharmony_ci Register arg2 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2); 2184514f5e3Sopenharmony_ci __ Str(arg2, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 2194514f5e3Sopenharmony_ci } 2204514f5e3Sopenharmony_ci if (argc > 1) { 2214514f5e3Sopenharmony_ci Register arg1 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); 2224514f5e3Sopenharmony_ci __ Str(arg1, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 2234514f5e3Sopenharmony_ci } 2244514f5e3Sopenharmony_ci if (argc > 0) { 2254514f5e3Sopenharmony_ci Register arg0 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); 2264514f5e3Sopenharmony_ci __ Str(arg0, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci} 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_civoid AsmInterpreterCall::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, 2324514f5e3Sopenharmony_ci Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow) 2334514f5e3Sopenharmony_ci{ 2344514f5e3Sopenharmony_ci Register glueRegister = __ GlueRegister(); 2354514f5e3Sopenharmony_ci Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); 2364514f5e3Sopenharmony_ci Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); 2374514f5e3Sopenharmony_ci Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV); 2384514f5e3Sopenharmony_ci Register currentSlotRegister = __ AvailableRegister3(); 2394514f5e3Sopenharmony_ci Register arg0 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); 2404514f5e3Sopenharmony_ci Register arg1 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); 2414514f5e3Sopenharmony_ci Label noExtraEntry; 2424514f5e3Sopenharmony_ci Label pushArgsEntry; 2434514f5e3Sopenharmony_ci 2444514f5e3Sopenharmony_ci auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode); 2454514f5e3Sopenharmony_ci Register declaredNumArgsRegister = __ AvailableRegister2(); 2464514f5e3Sopenharmony_ci __ Tbz(callFieldRegister, MethodLiteral::HaveExtraBit::START_BIT, &noExtraEntry); 2474514f5e3Sopenharmony_ci // extra entry 2484514f5e3Sopenharmony_ci { 2494514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 2504514f5e3Sopenharmony_ci Register tempArgcRegister = __ TempRegister1(); 2514514f5e3Sopenharmony_ci if (argc >= 0) { 2524514f5e3Sopenharmony_ci __ PushArgc(argc, tempArgcRegister, currentSlotRegister); 2534514f5e3Sopenharmony_ci } else { 2544514f5e3Sopenharmony_ci __ PushArgc(argcRegister, tempArgcRegister, currentSlotRegister); 2554514f5e3Sopenharmony_ci } 2564514f5e3Sopenharmony_ci // fall through 2574514f5e3Sopenharmony_ci } 2584514f5e3Sopenharmony_ci __ Bind(&noExtraEntry); 2594514f5e3Sopenharmony_ci { 2604514f5e3Sopenharmony_ci if (argc == 0) { 2614514f5e3Sopenharmony_ci { 2624514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope(assembler); 2634514f5e3Sopenharmony_ci Register tempRegister = __ TempRegister1(); 2644514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glueRegister, declaredNumArgsRegister, tempRegister, 2654514f5e3Sopenharmony_ci currentSlotRegister, nullptr, stackOverflow); 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci __ B(fastPathEntry); 2684514f5e3Sopenharmony_ci return; 2694514f5e3Sopenharmony_ci } 2704514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 2714514f5e3Sopenharmony_ci Register diffRegister = __ TempRegister1(); 2724514f5e3Sopenharmony_ci if (argc >= 0) { 2734514f5e3Sopenharmony_ci __ Sub(diffRegister.W(), declaredNumArgsRegister.W(), Immediate(argc)); 2744514f5e3Sopenharmony_ci } else { 2754514f5e3Sopenharmony_ci __ Sub(diffRegister.W(), declaredNumArgsRegister.W(), argcRegister.W()); 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister2Scope scope2(assembler); 2784514f5e3Sopenharmony_ci Register tempRegister = __ TempRegister2(); 2794514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glueRegister, diffRegister, tempRegister, 2804514f5e3Sopenharmony_ci currentSlotRegister, &pushArgsEntry, stackOverflow); 2814514f5e3Sopenharmony_ci __ B(fastPathEntry); 2824514f5e3Sopenharmony_ci } 2834514f5e3Sopenharmony_ci // declare < actual 2844514f5e3Sopenharmony_ci __ Bind(&pushArgsEntry); 2854514f5e3Sopenharmony_ci { 2864514f5e3Sopenharmony_ci __ Tbnz(callFieldRegister, MethodLiteral::HaveExtraBit::START_BIT, fastPathEntry); 2874514f5e3Sopenharmony_ci // no extra branch 2884514f5e3Sopenharmony_ci // arg1, declare must be 0 2894514f5e3Sopenharmony_ci if (argc == 1) { 2904514f5e3Sopenharmony_ci __ B(pushCallThis); 2914514f5e3Sopenharmony_ci return; 2924514f5e3Sopenharmony_ci } 2934514f5e3Sopenharmony_ci __ Cmp(declaredNumArgsRegister, Immediate(0)); 2944514f5e3Sopenharmony_ci __ B(Condition::EQ, pushCallThis); 2954514f5e3Sopenharmony_ci // call range 2964514f5e3Sopenharmony_ci if (argc < 0) { 2974514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope(assembler); 2984514f5e3Sopenharmony_ci Register opRegister = __ TempRegister1(); 2994514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glueRegister, declaredNumArgsRegister, 3004514f5e3Sopenharmony_ci argvRegister, opRegister, 3014514f5e3Sopenharmony_ci currentSlotRegister, nullptr, stackOverflow); 3024514f5e3Sopenharmony_ci } else if (argc > 0) { 3034514f5e3Sopenharmony_ci Label pushArgs0; 3044514f5e3Sopenharmony_ci if (argc > 2) { // 2: call arg2 3054514f5e3Sopenharmony_ci // decalare is 2 or 1 now 3064514f5e3Sopenharmony_ci __ Cmp(declaredNumArgsRegister, Immediate(1)); 3074514f5e3Sopenharmony_ci __ B(Condition::EQ, &pushArgs0); 3084514f5e3Sopenharmony_ci __ Str(arg1, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 3094514f5e3Sopenharmony_ci } 3104514f5e3Sopenharmony_ci if (argc > 1) { 3114514f5e3Sopenharmony_ci __ Bind(&pushArgs0); 3124514f5e3Sopenharmony_ci // decalare is is 1 now 3134514f5e3Sopenharmony_ci __ Str(arg0, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 3144514f5e3Sopenharmony_ci } 3154514f5e3Sopenharmony_ci } 3164514f5e3Sopenharmony_ci __ B(pushCallThis); 3174514f5e3Sopenharmony_ci } 3184514f5e3Sopenharmony_ci} 3194514f5e3Sopenharmony_ci 3204514f5e3Sopenharmony_ciRegister AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister) 3214514f5e3Sopenharmony_ci{ 3224514f5e3Sopenharmony_ci switch (mode) { 3234514f5e3Sopenharmony_ci case JSCallMode::CALL_GETTER: 3244514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARG0: 3254514f5e3Sopenharmony_ci return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); 3264514f5e3Sopenharmony_ci case JSCallMode::CALL_SETTER: 3274514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARG1: 3284514f5e3Sopenharmony_ci return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); 3294514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARG2: 3304514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARG2_WITH_RETURN: 3314514f5e3Sopenharmony_ci case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: 3324514f5e3Sopenharmony_ci case JSCallMode::SUPER_CALL_WITH_ARGV: 3334514f5e3Sopenharmony_ci case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV: 3344514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_WITH_ARGV: 3354514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: 3364514f5e3Sopenharmony_ci return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2); 3374514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARG3: 3384514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_ARG3_WITH_RETURN: 3394514f5e3Sopenharmony_ci return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG3); 3404514f5e3Sopenharmony_ci case JSCallMode::CALL_FROM_AOT: 3414514f5e3Sopenharmony_ci case JSCallMode::CALL_ENTRY: { 3424514f5e3Sopenharmony_ci Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); 3434514f5e3Sopenharmony_ci __ Ldur(defaultRegister, MemoryOperand(argvRegister, -FRAME_SLOT_SIZE)); 3444514f5e3Sopenharmony_ci return defaultRegister; 3454514f5e3Sopenharmony_ci } 3464514f5e3Sopenharmony_ci default: 3474514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 3484514f5e3Sopenharmony_ci UNREACHABLE(); 3494514f5e3Sopenharmony_ci } 3504514f5e3Sopenharmony_ci return INVALID_REG; 3514514f5e3Sopenharmony_ci} 3524514f5e3Sopenharmony_ci 3534514f5e3Sopenharmony_ciRegister AsmInterpreterCall::GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, 3544514f5e3Sopenharmony_ci Register defaultRegister) 3554514f5e3Sopenharmony_ci{ 3564514f5e3Sopenharmony_ci switch (mode) { 3574514f5e3Sopenharmony_ci case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: 3584514f5e3Sopenharmony_ci case JSCallMode::CALL_THIS_WITH_ARGV: 3594514f5e3Sopenharmony_ci return __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); 3604514f5e3Sopenharmony_ci case JSCallMode::SUPER_CALL_WITH_ARGV: 3614514f5e3Sopenharmony_ci case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV: 3624514f5e3Sopenharmony_ci return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG3); 3634514f5e3Sopenharmony_ci case JSCallMode::CALL_FROM_AOT: 3644514f5e3Sopenharmony_ci case JSCallMode::CALL_ENTRY: { 3654514f5e3Sopenharmony_ci Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); 3664514f5e3Sopenharmony_ci // 2: new Target index 3674514f5e3Sopenharmony_ci __ Ldur(defaultRegister, MemoryOperand(argvRegister, -2 * FRAME_SLOT_SIZE)); 3684514f5e3Sopenharmony_ci return defaultRegister; 3694514f5e3Sopenharmony_ci } 3704514f5e3Sopenharmony_ci default: 3714514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 3724514f5e3Sopenharmony_ci UNREACHABLE(); 3734514f5e3Sopenharmony_ci } 3744514f5e3Sopenharmony_ci return INVALID_REG; 3754514f5e3Sopenharmony_ci} 3764514f5e3Sopenharmony_ci 3774514f5e3Sopenharmony_ci// void PushCallArgsxAndDispatch(uintptr_t glue, uintptr_t sp, uint64_t callTarget, uintptr_t method, 3784514f5e3Sopenharmony_ci// uint64_t callField, ...) 3794514f5e3Sopenharmony_ci// GHC calling convention 3804514f5e3Sopenharmony_ci// Input1: for callarg0/1/2/3 Input2: for callrange 3814514f5e3Sopenharmony_ci// X19 - glue // X19 - glue 3824514f5e3Sopenharmony_ci// FP - sp // FP - sp 3834514f5e3Sopenharmony_ci// X20 - callTarget // X20 - callTarget 3844514f5e3Sopenharmony_ci// X21 - method // X21 - method 3854514f5e3Sopenharmony_ci// X22 - callField // X22 - callField 3864514f5e3Sopenharmony_ci// X23 - arg0 // X23 - actualArgc 3874514f5e3Sopenharmony_ci// X24 - arg1 // X24 - argv 3884514f5e3Sopenharmony_ci// X25 - arg2 3894514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisRangeAndDispatch(ExtendedAssembler *assembler) 3904514f5e3Sopenharmony_ci{ 3914514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallThisRangeAndDispatch)); 3924514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER); 3934514f5e3Sopenharmony_ci} 3944514f5e3Sopenharmony_ci 3954514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallRangeAndDispatch(ExtendedAssembler *assembler) 3964514f5e3Sopenharmony_ci{ 3974514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallRangeAndDispatch)); 3984514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER); 3994514f5e3Sopenharmony_ci} 4004514f5e3Sopenharmony_ci 4014514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallNewAndDispatch(ExtendedAssembler *assembler) 4024514f5e3Sopenharmony_ci{ 4034514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallNewAndDispatch)); 4044514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER); 4054514f5e3Sopenharmony_ci} 4064514f5e3Sopenharmony_ci 4074514f5e3Sopenharmony_civoid AsmInterpreterCall::PushSuperCallAndDispatch(ExtendedAssembler *assembler) 4084514f5e3Sopenharmony_ci{ 4094514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushSuperCallAndDispatch)); 4104514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::SUPER_CALL_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER); 4114514f5e3Sopenharmony_ci} 4124514f5e3Sopenharmony_ci 4134514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArgs3AndDispatch(ExtendedAssembler *assembler) 4144514f5e3Sopenharmony_ci{ 4154514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallArgs3AndDispatch)); 4164514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_ARG3, FrameTransitionType::OTHER_TO_OTHER); 4174514f5e3Sopenharmony_ci} 4184514f5e3Sopenharmony_ci 4194514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArgs2AndDispatch(ExtendedAssembler *assembler) 4204514f5e3Sopenharmony_ci{ 4214514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallArgs2AndDispatch)); 4224514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_ARG2, FrameTransitionType::OTHER_TO_OTHER); 4234514f5e3Sopenharmony_ci} 4244514f5e3Sopenharmony_ci 4254514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArg1AndDispatch(ExtendedAssembler *assembler) 4264514f5e3Sopenharmony_ci{ 4274514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallArg1AndDispatch)); 4284514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_ARG1, FrameTransitionType::OTHER_TO_OTHER); 4294514f5e3Sopenharmony_ci} 4304514f5e3Sopenharmony_ci 4314514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArg0AndDispatch(ExtendedAssembler *assembler) 4324514f5e3Sopenharmony_ci{ 4334514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallArg0AndDispatch)); 4344514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_ARG0, FrameTransitionType::OTHER_TO_OTHER); 4354514f5e3Sopenharmony_ci} 4364514f5e3Sopenharmony_ci 4374514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArg0AndDispatch(ExtendedAssembler *assembler) 4384514f5e3Sopenharmony_ci{ 4394514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallThisArg0AndDispatch)); 4404514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG0, FrameTransitionType::OTHER_TO_OTHER); 4414514f5e3Sopenharmony_ci} 4424514f5e3Sopenharmony_ci 4434514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArg1AndDispatch(ExtendedAssembler *assembler) 4444514f5e3Sopenharmony_ci{ 4454514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallThisArg1AndDispatch)); 4464514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG1, FrameTransitionType::OTHER_TO_OTHER); 4474514f5e3Sopenharmony_ci} 4484514f5e3Sopenharmony_ci 4494514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler) 4504514f5e3Sopenharmony_ci{ 4514514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallThisArgs2AndDispatch)); 4524514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG2, FrameTransitionType::OTHER_TO_OTHER); 4534514f5e3Sopenharmony_ci} 4544514f5e3Sopenharmony_ci 4554514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler) 4564514f5e3Sopenharmony_ci{ 4574514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallThisArgs3AndDispatch)); 4584514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG3, FrameTransitionType::OTHER_TO_OTHER); 4594514f5e3Sopenharmony_ci} 4604514f5e3Sopenharmony_ci 4614514f5e3Sopenharmony_ci// uint64_t PushCallRangeAndDispatchNative(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, uintptr_t argv[]) 4624514f5e3Sopenharmony_ci// c++ calling convention call js function 4634514f5e3Sopenharmony_ci// Input: X0 - glue 4644514f5e3Sopenharmony_ci// X1 - nativeCode 4654514f5e3Sopenharmony_ci// X2 - callTarget 4664514f5e3Sopenharmony_ci// X3 - thisValue 4674514f5e3Sopenharmony_ci// X4 - argc 4684514f5e3Sopenharmony_ci// X5 - argV (...) 4694514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallRangeAndDispatchNative(ExtendedAssembler *assembler) 4704514f5e3Sopenharmony_ci{ 4714514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallRangeAndDispatchNative)); 4724514f5e3Sopenharmony_ci CallNativeWithArgv(assembler, false); 4734514f5e3Sopenharmony_ci} 4744514f5e3Sopenharmony_ci 4754514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallNewAndDispatchNative(ExtendedAssembler *assembler) 4764514f5e3Sopenharmony_ci{ 4774514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallNewAndDispatchNative)); 4784514f5e3Sopenharmony_ci CallNativeWithArgv(assembler, true); 4794514f5e3Sopenharmony_ci} 4804514f5e3Sopenharmony_ci 4814514f5e3Sopenharmony_civoid AsmInterpreterCall::PushNewTargetAndDispatchNative(ExtendedAssembler *assembler) 4824514f5e3Sopenharmony_ci{ 4834514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushNewTargetAndDispatchNative)); 4844514f5e3Sopenharmony_ci CallNativeWithArgv(assembler, true, true); 4854514f5e3Sopenharmony_ci} 4864514f5e3Sopenharmony_ci 4874514f5e3Sopenharmony_civoid AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget) 4884514f5e3Sopenharmony_ci{ 4894514f5e3Sopenharmony_ci Register glue(X0); 4904514f5e3Sopenharmony_ci Register nativeCode(X1); 4914514f5e3Sopenharmony_ci Register callTarget(X2); 4924514f5e3Sopenharmony_ci Register thisObj(X3); 4934514f5e3Sopenharmony_ci Register argc(X4); 4944514f5e3Sopenharmony_ci Register argv(X5); 4954514f5e3Sopenharmony_ci Register newTarget(X6); 4964514f5e3Sopenharmony_ci Register opArgc(X8); 4974514f5e3Sopenharmony_ci Register opArgv(X9); 4984514f5e3Sopenharmony_ci Register temp(X10); 4994514f5e3Sopenharmony_ci Register currentSlotRegister(X11); 5004514f5e3Sopenharmony_ci Register spRegister(SP); 5014514f5e3Sopenharmony_ci 5024514f5e3Sopenharmony_ci Label pushThis; 5034514f5e3Sopenharmony_ci Label stackOverflow; 5044514f5e3Sopenharmony_ci bool isFrameComplete = PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME_WITH_ARGV, temp, argc); 5054514f5e3Sopenharmony_ci 5064514f5e3Sopenharmony_ci __ Mov(currentSlotRegister, spRegister); 5074514f5e3Sopenharmony_ci // Reserve enough sp space to prevent stack parameters from being covered by cpu profiler. 5084514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false))); 5094514f5e3Sopenharmony_ci __ Mov(Register(SP), temp); 5104514f5e3Sopenharmony_ci 5114514f5e3Sopenharmony_ci __ Mov(opArgc, argc); 5124514f5e3Sopenharmony_ci __ Mov(opArgv, argv); 5134514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, opArgc, opArgv, temp, currentSlotRegister, &pushThis, &stackOverflow); 5144514f5e3Sopenharmony_ci 5154514f5e3Sopenharmony_ci __ Bind(&pushThis); 5164514f5e3Sopenharmony_ci // newTarget 5174514f5e3Sopenharmony_ci if (callNew) { 5184514f5e3Sopenharmony_ci if (hasNewTarget) { 5194514f5e3Sopenharmony_ci // 16: this & newTarget 5204514f5e3Sopenharmony_ci __ Stp(newTarget, thisObj, MemoryOperand(currentSlotRegister, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); 5214514f5e3Sopenharmony_ci } else { 5224514f5e3Sopenharmony_ci // 16: this & newTarget 5234514f5e3Sopenharmony_ci __ Stp(callTarget, thisObj, MemoryOperand(currentSlotRegister, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); 5244514f5e3Sopenharmony_ci } 5254514f5e3Sopenharmony_ci } else { 5264514f5e3Sopenharmony_ci __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 5274514f5e3Sopenharmony_ci // 16: this & newTarget 5284514f5e3Sopenharmony_ci __ Stp(temp, thisObj, MemoryOperand(currentSlotRegister, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); 5294514f5e3Sopenharmony_ci } 5304514f5e3Sopenharmony_ci // callTarget 5314514f5e3Sopenharmony_ci __ Str(callTarget, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 5324514f5e3Sopenharmony_ci __ Add(temp, currentSlotRegister, Immediate(QUINTUPLE_SLOT_SIZE)); 5334514f5e3Sopenharmony_ci if (!isFrameComplete) { 5344514f5e3Sopenharmony_ci __ Add(Register(FP), temp, Operand(argc, LSL, 3)); // 3: argc * 8 5354514f5e3Sopenharmony_ci } 5364514f5e3Sopenharmony_ci 5374514f5e3Sopenharmony_ci __ Add(temp, argc, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); 5384514f5e3Sopenharmony_ci // 2: thread & argc 5394514f5e3Sopenharmony_ci __ Stp(glue, temp, MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 5404514f5e3Sopenharmony_ci __ Add(Register(X0), currentSlotRegister, Immediate(0)); 5414514f5e3Sopenharmony_ci 5424514f5e3Sopenharmony_ci __ Align16(currentSlotRegister); 5434514f5e3Sopenharmony_ci __ Mov(spRegister, currentSlotRegister); 5444514f5e3Sopenharmony_ci 5454514f5e3Sopenharmony_ci CallNativeInternal(assembler, nativeCode); 5464514f5e3Sopenharmony_ci __ Ret(); 5474514f5e3Sopenharmony_ci 5484514f5e3Sopenharmony_ci __ Bind(&stackOverflow); 5494514f5e3Sopenharmony_ci { 5504514f5e3Sopenharmony_ci // use builtin_with_argv_frame to mark gc map 5514514f5e3Sopenharmony_ci Register frameType(X11); 5524514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); 5534514f5e3Sopenharmony_ci __ Mov(spRegister, temp); 5544514f5e3Sopenharmony_ci __ Mov(frameType, Immediate(static_cast<int32_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME))); 5554514f5e3Sopenharmony_ci // 2: frame type and argc 5564514f5e3Sopenharmony_ci __ Stp(Register(Zero), frameType, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); 5574514f5e3Sopenharmony_ci __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 5584514f5e3Sopenharmony_ci // 2: fill this&newtgt slots 5594514f5e3Sopenharmony_ci __ Stp(temp, temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); 5604514f5e3Sopenharmony_ci // 2: fill func&align slots 5614514f5e3Sopenharmony_ci __ Stp(Register(Zero), temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); 5624514f5e3Sopenharmony_ci __ Mov(temp, spRegister); 5634514f5e3Sopenharmony_ci // 6:frame type, argc, this, newTarget, func and align 5644514f5e3Sopenharmony_ci // +----------------------------------------------------------------+ <---- fp = sp + 6 * frame_slot_size 5654514f5e3Sopenharmony_ci // | FrameType = BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME | 5664514f5e3Sopenharmony_ci // +----------------------------------------------------------------+ 5674514f5e3Sopenharmony_ci // | argc = 0 | 5684514f5e3Sopenharmony_ci // |----------------------------------------------------------------| 5694514f5e3Sopenharmony_ci // | this = undefined | 5704514f5e3Sopenharmony_ci // |----------------------------------------------------------------| 5714514f5e3Sopenharmony_ci // | newTarget = undefine | 5724514f5e3Sopenharmony_ci // |----------------------------------------------------------------| 5734514f5e3Sopenharmony_ci // | function = undefined | 5744514f5e3Sopenharmony_ci // |----------------------------------------------------------------| 5754514f5e3Sopenharmony_ci // | align | 5764514f5e3Sopenharmony_ci // +----------------------------------------------------------------+ <---- sp 5774514f5e3Sopenharmony_ci __ Add(Register(FP), temp, Immediate(FRAME_SLOT_SIZE * 6)); 5784514f5e3Sopenharmony_ci 5794514f5e3Sopenharmony_ci Register runtimeId(X11); 5804514f5e3Sopenharmony_ci Register trampoline(X12); 5814514f5e3Sopenharmony_ci __ Mov(runtimeId, Immediate(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException)); 5824514f5e3Sopenharmony_ci // 3 : 3 means *8 5834514f5e3Sopenharmony_ci __ Add(trampoline, glue, Operand(runtimeId, LSL, 3)); 5844514f5e3Sopenharmony_ci __ Ldr(trampoline, MemoryOperand(trampoline, JSThread::GlueData::GetRTStubEntriesOffset(false))); 5854514f5e3Sopenharmony_ci __ Blr(trampoline); 5864514f5e3Sopenharmony_ci 5874514f5e3Sopenharmony_ci // resume rsp 5884514f5e3Sopenharmony_ci __ Mov(Register(SP), Register(FP)); 5894514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 5904514f5e3Sopenharmony_ci __ Ret(); 5914514f5e3Sopenharmony_ci } 5924514f5e3Sopenharmony_ci} 5934514f5e3Sopenharmony_ci 5944514f5e3Sopenharmony_ci// uint64_t PushCallArgsAndDispatchNative(uintptr_t codeAddress, uintptr_t glue, uint32_t argc, ...) 5954514f5e3Sopenharmony_ci// webkit_jscc calling convention call runtime_id's runtion function(c-abi) 5964514f5e3Sopenharmony_ci// Input: X0 - codeAddress 5974514f5e3Sopenharmony_ci// stack layout: sp + N*8 argvN 5984514f5e3Sopenharmony_ci// ........ 5994514f5e3Sopenharmony_ci// sp + 24: argv1 6004514f5e3Sopenharmony_ci// sp + 16: argv0 6014514f5e3Sopenharmony_ci// sp + 8: actualArgc 6024514f5e3Sopenharmony_ci// sp: thread 6034514f5e3Sopenharmony_ci// construct Native Leave Frame 6044514f5e3Sopenharmony_ci// +--------------------------+ 6054514f5e3Sopenharmony_ci// | argV[N - 1] | 6064514f5e3Sopenharmony_ci// |--------------------------| 6074514f5e3Sopenharmony_ci// | . . . . | 6084514f5e3Sopenharmony_ci// |--------------------------+ 6094514f5e3Sopenharmony_ci// | argV[2]=this | 6104514f5e3Sopenharmony_ci// +--------------------------+ 6114514f5e3Sopenharmony_ci// | argV[1]=new-target | 6124514f5e3Sopenharmony_ci// +--------------------------+ 6134514f5e3Sopenharmony_ci// | argV[0]=call-target | 6144514f5e3Sopenharmony_ci// +--------------------------+ --------- 6154514f5e3Sopenharmony_ci// | argc | ^ 6164514f5e3Sopenharmony_ci// |--------------------------| | 6174514f5e3Sopenharmony_ci// | thread | | 6184514f5e3Sopenharmony_ci// |--------------------------| | 6194514f5e3Sopenharmony_ci// | returnAddr | BuiltinFrame 6204514f5e3Sopenharmony_ci// |--------------------------| | 6214514f5e3Sopenharmony_ci// | callsiteFp | | 6224514f5e3Sopenharmony_ci// |--------------------------| | 6234514f5e3Sopenharmony_ci// | frameType | v 6244514f5e3Sopenharmony_ci// +--------------------------+ --------- 6254514f5e3Sopenharmony_ci 6264514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArgsAndDispatchNative(ExtendedAssembler *assembler) 6274514f5e3Sopenharmony_ci{ 6284514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(PushCallArgsAndDispatchNative)); 6294514f5e3Sopenharmony_ci 6304514f5e3Sopenharmony_ci Register nativeCode(X0); 6314514f5e3Sopenharmony_ci Register glue(X1); 6324514f5e3Sopenharmony_ci Register argv(X5); 6334514f5e3Sopenharmony_ci Register temp(X6); 6344514f5e3Sopenharmony_ci Register sp(SP); 6354514f5e3Sopenharmony_ci Register nativeCodeTemp(X2); 6364514f5e3Sopenharmony_ci 6374514f5e3Sopenharmony_ci __ Mov(nativeCodeTemp, nativeCode); 6384514f5e3Sopenharmony_ci 6394514f5e3Sopenharmony_ci __ Ldr(glue, MemoryOperand(sp, 0)); 6404514f5e3Sopenharmony_ci __ Add(Register(X0), sp, Immediate(0)); 6414514f5e3Sopenharmony_ci PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME, temp, argv); 6424514f5e3Sopenharmony_ci 6434514f5e3Sopenharmony_ci CallNativeInternal(assembler, nativeCodeTemp); 6444514f5e3Sopenharmony_ci __ Ret(); 6454514f5e3Sopenharmony_ci} 6464514f5e3Sopenharmony_ci 6474514f5e3Sopenharmony_cibool AsmInterpreterCall::PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, 6484514f5e3Sopenharmony_ci FrameType type, Register op, Register next) 6494514f5e3Sopenharmony_ci{ 6504514f5e3Sopenharmony_ci Register sp(SP); 6514514f5e3Sopenharmony_ci __ PushFpAndLr(); 6524514f5e3Sopenharmony_ci __ Mov(op, sp); 6534514f5e3Sopenharmony_ci __ Str(op, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); 6544514f5e3Sopenharmony_ci __ Mov(op, Immediate(static_cast<int32_t>(type))); 6554514f5e3Sopenharmony_ci if (type == FrameType::BUILTIN_FRAME) { 6564514f5e3Sopenharmony_ci // push stack args 6574514f5e3Sopenharmony_ci __ Add(next, sp, Immediate(BuiltinFrame::GetStackArgsToFpDelta(false))); 6584514f5e3Sopenharmony_ci // 2: -2 * FRAME_SLOT_SIZE means type & next 6594514f5e3Sopenharmony_ci __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 6604514f5e3Sopenharmony_ci // 2: 2 * FRAME_SLOT_SIZE means skip next and frame type 6614514f5e3Sopenharmony_ci __ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE)); 6624514f5e3Sopenharmony_ci return true; 6634514f5e3Sopenharmony_ci } else if (type == FrameType::BUILTIN_ENTRY_FRAME) { 6644514f5e3Sopenharmony_ci // 2: -2 * FRAME_SLOT_SIZE means type & next 6654514f5e3Sopenharmony_ci __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 6664514f5e3Sopenharmony_ci // 2: 2 * FRAME_SLOT_SIZE means skip next and frame type 6674514f5e3Sopenharmony_ci __ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE)); 6684514f5e3Sopenharmony_ci return true; 6694514f5e3Sopenharmony_ci } else if (type == FrameType::BUILTIN_FRAME_WITH_ARGV) { 6704514f5e3Sopenharmony_ci // this frame push stack args must before update FP, otherwise cpu profiler maybe visit incomplete stack 6714514f5e3Sopenharmony_ci // BuiltinWithArgvFrame layout please see frames.h 6724514f5e3Sopenharmony_ci // 2: -2 * FRAME_SLOT_SIZE means type & next 6734514f5e3Sopenharmony_ci __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 6744514f5e3Sopenharmony_ci return false; 6754514f5e3Sopenharmony_ci } else { 6764514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 6774514f5e3Sopenharmony_ci UNREACHABLE(); 6784514f5e3Sopenharmony_ci } 6794514f5e3Sopenharmony_ci} 6804514f5e3Sopenharmony_ci 6814514f5e3Sopenharmony_civoid AsmInterpreterCall::CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode) 6824514f5e3Sopenharmony_ci{ 6834514f5e3Sopenharmony_ci __ Blr(nativeCode); 6844514f5e3Sopenharmony_ci // resume rsp 6854514f5e3Sopenharmony_ci __ Mov(Register(SP), Register(FP)); 6864514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 6874514f5e3Sopenharmony_ci} 6884514f5e3Sopenharmony_ci 6894514f5e3Sopenharmony_ci// ResumeRspAndDispatch(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool, 6904514f5e3Sopenharmony_ci// uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter, size_t jumpSize) 6914514f5e3Sopenharmony_ci// GHC calling convention 6924514f5e3Sopenharmony_ci// X19 - glue 6934514f5e3Sopenharmony_ci// FP - sp 6944514f5e3Sopenharmony_ci// X20 - pc 6954514f5e3Sopenharmony_ci// X21 - constantPool 6964514f5e3Sopenharmony_ci// X22 - profileTypeInfo 6974514f5e3Sopenharmony_ci// X23 - acc 6984514f5e3Sopenharmony_ci// X24 - hotnessCounter 6994514f5e3Sopenharmony_ci// X25 - jumpSizeAfterCall 7004514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndDispatch(ExtendedAssembler *assembler) 7014514f5e3Sopenharmony_ci{ 7024514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndDispatch)); 7034514f5e3Sopenharmony_ci 7044514f5e3Sopenharmony_ci Register glueRegister = __ GlueRegister(); 7054514f5e3Sopenharmony_ci Register sp(FP); 7064514f5e3Sopenharmony_ci Register rsp(SP); 7074514f5e3Sopenharmony_ci Register pc(X20); 7084514f5e3Sopenharmony_ci Register jumpSizeRegister(X25); 7094514f5e3Sopenharmony_ci 7104514f5e3Sopenharmony_ci Register ret(X23); 7114514f5e3Sopenharmony_ci Register opcode(X6, W); 7124514f5e3Sopenharmony_ci Register temp(X7); 7134514f5e3Sopenharmony_ci Register bcStub(X7); 7144514f5e3Sopenharmony_ci Register fp(X8); 7154514f5e3Sopenharmony_ci 7164514f5e3Sopenharmony_ci int64_t fpOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false)) 7174514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 7184514f5e3Sopenharmony_ci int64_t spOffset = static_cast<int64_t>(AsmInterpretedFrame::GetBaseOffset(false)) 7194514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 7204514f5e3Sopenharmony_ci int64_t thisOffset = static_cast<int64_t>(AsmInterpretedFrame::GetThisOffset(false)) 7214514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 7224514f5e3Sopenharmony_ci ASSERT(fpOffset < 0); 7234514f5e3Sopenharmony_ci ASSERT(spOffset < 0); 7244514f5e3Sopenharmony_ci 7254514f5e3Sopenharmony_ci Label newObjectRangeReturn; 7264514f5e3Sopenharmony_ci Label dispatch; 7274514f5e3Sopenharmony_ci __ Ldur(fp, MemoryOperand(sp, fpOffset)); // store fp for temporary 7284514f5e3Sopenharmony_ci __ Cmp(jumpSizeRegister, Immediate(0)); 7294514f5e3Sopenharmony_ci __ B(Condition::LE, &newObjectRangeReturn); 7304514f5e3Sopenharmony_ci __ Ldur(sp, MemoryOperand(sp, spOffset)); // update sp 7314514f5e3Sopenharmony_ci 7324514f5e3Sopenharmony_ci __ Add(pc, pc, Operand(jumpSizeRegister, LSL, 0)); 7334514f5e3Sopenharmony_ci __ Ldrb(opcode, MemoryOperand(pc, 0)); 7344514f5e3Sopenharmony_ci __ Bind(&dispatch); 7354514f5e3Sopenharmony_ci { 7364514f5e3Sopenharmony_ci __ Mov(rsp, fp); // resume rsp 7374514f5e3Sopenharmony_ci __ Add(bcStub, glueRegister, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2)); 7384514f5e3Sopenharmony_ci __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false))); 7394514f5e3Sopenharmony_ci __ Br(bcStub); 7404514f5e3Sopenharmony_ci } 7414514f5e3Sopenharmony_ci 7424514f5e3Sopenharmony_ci Label getThis; 7434514f5e3Sopenharmony_ci Label notUndefined; 7444514f5e3Sopenharmony_ci __ Bind(&newObjectRangeReturn); 7454514f5e3Sopenharmony_ci { 7464514f5e3Sopenharmony_ci __ Cmp(ret, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 7474514f5e3Sopenharmony_ci __ B(Condition::NE, ¬Undefined); 7484514f5e3Sopenharmony_ci ASSERT(thisOffset < 0); 7494514f5e3Sopenharmony_ci __ Bind(&getThis); 7504514f5e3Sopenharmony_ci __ Ldur(ret, MemoryOperand(sp, thisOffset)); // update acc 7514514f5e3Sopenharmony_ci __ Ldur(sp, MemoryOperand(sp, spOffset)); // update sp 7524514f5e3Sopenharmony_ci __ Mov(rsp, fp); // resume rsp 7534514f5e3Sopenharmony_ci __ Sub(pc, pc, jumpSizeRegister); // sub negative jmupSize 7544514f5e3Sopenharmony_ci __ Ldrb(opcode, MemoryOperand(pc, 0)); 7554514f5e3Sopenharmony_ci __ Add(bcStub, glueRegister, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2)); 7564514f5e3Sopenharmony_ci __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false))); 7574514f5e3Sopenharmony_ci __ Br(bcStub); 7584514f5e3Sopenharmony_ci } 7594514f5e3Sopenharmony_ci __ Bind(¬Undefined); 7604514f5e3Sopenharmony_ci { 7614514f5e3Sopenharmony_ci Label notEcmaObject; 7624514f5e3Sopenharmony_ci __ Mov(temp, Immediate(JSTaggedValue::TAG_HEAPOBJECT_MASK)); 7634514f5e3Sopenharmony_ci __ And(temp, temp, ret); 7644514f5e3Sopenharmony_ci __ Cmp(temp, Immediate(0)); 7654514f5e3Sopenharmony_ci __ B(Condition::NE, ¬EcmaObject); 7664514f5e3Sopenharmony_ci // acc is heap object 7674514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(ret, TaggedObject::HCLASS_OFFSET)); 7684514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, JSHClass::BIT_FIELD_OFFSET)); 7694514f5e3Sopenharmony_ci __ And(temp.W(), temp.W(), LogicalImmediate::Create(0xFF, RegWSize)); 7704514f5e3Sopenharmony_ci __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_LAST))); 7714514f5e3Sopenharmony_ci __ B(Condition::HI, ¬EcmaObject); 7724514f5e3Sopenharmony_ci __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_FIRST))); 7734514f5e3Sopenharmony_ci __ B(Condition::LO, ¬EcmaObject); 7744514f5e3Sopenharmony_ci // acc is ecma object 7754514f5e3Sopenharmony_ci __ Ldur(sp, MemoryOperand(sp, spOffset)); // update sp 7764514f5e3Sopenharmony_ci __ Sub(pc, pc, jumpSizeRegister); // sub negative jmupSize 7774514f5e3Sopenharmony_ci __ Ldrb(opcode, MemoryOperand(pc, 0)); 7784514f5e3Sopenharmony_ci __ B(&dispatch); 7794514f5e3Sopenharmony_ci 7804514f5e3Sopenharmony_ci __ Bind(¬EcmaObject); 7814514f5e3Sopenharmony_ci { 7824514f5e3Sopenharmony_ci int64_t constructorOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFunctionOffset(false)) 7834514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 7844514f5e3Sopenharmony_ci ASSERT(constructorOffset < 0); 7854514f5e3Sopenharmony_ci __ Ldur(temp, MemoryOperand(sp, constructorOffset)); // load constructor 7864514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, JSFunctionBase::METHOD_OFFSET)); 7874514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, Method::EXTRA_LITERAL_INFO_OFFSET)); 7884514f5e3Sopenharmony_ci __ Lsr(temp.W(), temp.W(), MethodLiteral::FunctionKindBits::START_BIT); 7894514f5e3Sopenharmony_ci __ And(temp.W(), temp.W(), 7904514f5e3Sopenharmony_ci LogicalImmediate::Create((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1, RegWSize)); 7914514f5e3Sopenharmony_ci __ Cmp(temp.W(), Immediate(static_cast<int64_t>(FunctionKind::CLASS_CONSTRUCTOR))); 7924514f5e3Sopenharmony_ci __ B(Condition::LS, &getThis); // constructor is base 7934514f5e3Sopenharmony_ci // exception branch 7944514f5e3Sopenharmony_ci { 7954514f5e3Sopenharmony_ci __ Mov(opcode, kungfu::BytecodeStubCSigns::ID_NewObjectRangeThrowException); 7964514f5e3Sopenharmony_ci __ Ldur(sp, MemoryOperand(sp, spOffset)); // update sp 7974514f5e3Sopenharmony_ci __ B(&dispatch); 7984514f5e3Sopenharmony_ci } 7994514f5e3Sopenharmony_ci } 8004514f5e3Sopenharmony_ci } 8014514f5e3Sopenharmony_ci} 8024514f5e3Sopenharmony_ci 8034514f5e3Sopenharmony_ci// ResumeRspAndReturn(uintptr_t acc) 8044514f5e3Sopenharmony_ci// GHC calling convention 8054514f5e3Sopenharmony_ci// X19 - acc 8064514f5e3Sopenharmony_ci// FP - prevSp 8074514f5e3Sopenharmony_ci// X20 - sp 8084514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndReturn(ExtendedAssembler *assembler) 8094514f5e3Sopenharmony_ci{ 8104514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturn)); 8114514f5e3Sopenharmony_ci Register rsp(SP); 8124514f5e3Sopenharmony_ci Register currentSp(X20); 8134514f5e3Sopenharmony_ci 8144514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 8154514f5e3Sopenharmony_ci Register fpRegister = __ TempRegister1(); 8164514f5e3Sopenharmony_ci int64_t offset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false)) 8174514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 8184514f5e3Sopenharmony_ci ASSERT(offset < 0); 8194514f5e3Sopenharmony_ci __ Ldur(fpRegister, MemoryOperand(currentSp, offset)); 8204514f5e3Sopenharmony_ci __ Mov(rsp, fpRegister); 8214514f5e3Sopenharmony_ci 8224514f5e3Sopenharmony_ci // return 8234514f5e3Sopenharmony_ci { 8244514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 8254514f5e3Sopenharmony_ci __ Mov(Register(X0), Register(X19)); 8264514f5e3Sopenharmony_ci __ Ret(); 8274514f5e3Sopenharmony_ci } 8284514f5e3Sopenharmony_ci} 8294514f5e3Sopenharmony_ci 8304514f5e3Sopenharmony_ci// ResumeRspAndReturnBaseline(uintptr_t acc) 8314514f5e3Sopenharmony_ci// GHC calling convention 8324514f5e3Sopenharmony_ci// X19 - acc 8334514f5e3Sopenharmony_ci// FP - prevSp 8344514f5e3Sopenharmony_ci// X20 - sp 8354514f5e3Sopenharmony_ci// X21 - jumpSizeAfterCall 8364514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndReturnBaseline(ExtendedAssembler *assembler) 8374514f5e3Sopenharmony_ci{ 8384514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturnBaseline)); 8394514f5e3Sopenharmony_ci Register rsp(SP); 8404514f5e3Sopenharmony_ci Register currentSp(X20); 8414514f5e3Sopenharmony_ci 8424514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 8434514f5e3Sopenharmony_ci Register fpRegister = __ TempRegister1(); 8444514f5e3Sopenharmony_ci int64_t fpOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false)) - 8454514f5e3Sopenharmony_ci static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 8464514f5e3Sopenharmony_ci ASSERT(fpOffset < 0); 8474514f5e3Sopenharmony_ci __ Ldur(fpRegister, MemoryOperand(currentSp, fpOffset)); 8484514f5e3Sopenharmony_ci __ Mov(rsp, fpRegister); 8494514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 8504514f5e3Sopenharmony_ci __ Mov(Register(X0), Register(X19)); 8514514f5e3Sopenharmony_ci 8524514f5e3Sopenharmony_ci // Check and set result 8534514f5e3Sopenharmony_ci Register ret = X0; 8544514f5e3Sopenharmony_ci Register jumpSizeRegister = X21; 8554514f5e3Sopenharmony_ci Label getThis; 8564514f5e3Sopenharmony_ci Label notUndefined; 8574514f5e3Sopenharmony_ci Label normalReturn; 8584514f5e3Sopenharmony_ci Label newObjectRangeReturn; 8594514f5e3Sopenharmony_ci __ Cmp(jumpSizeRegister, Immediate(0)); 8604514f5e3Sopenharmony_ci __ B(Condition::GT, &normalReturn); 8614514f5e3Sopenharmony_ci 8624514f5e3Sopenharmony_ci __ Bind(&newObjectRangeReturn); 8634514f5e3Sopenharmony_ci { 8644514f5e3Sopenharmony_ci __ Cmp(ret, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 8654514f5e3Sopenharmony_ci __ B(Condition::NE, ¬Undefined); 8664514f5e3Sopenharmony_ci 8674514f5e3Sopenharmony_ci __ Bind(&getThis); 8684514f5e3Sopenharmony_ci int64_t thisOffset = static_cast<int64_t>(AsmInterpretedFrame::GetThisOffset(false)) - 8694514f5e3Sopenharmony_ci static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 8704514f5e3Sopenharmony_ci ASSERT(thisOffset < 0); 8714514f5e3Sopenharmony_ci __ Ldur(ret, MemoryOperand(currentSp, thisOffset)); // update result 8724514f5e3Sopenharmony_ci __ B(&normalReturn); 8734514f5e3Sopenharmony_ci 8744514f5e3Sopenharmony_ci __ Bind(¬Undefined); 8754514f5e3Sopenharmony_ci { 8764514f5e3Sopenharmony_ci Register temp = X19; 8774514f5e3Sopenharmony_ci Label notEcmaObject; 8784514f5e3Sopenharmony_ci __ Mov(temp, Immediate(JSTaggedValue::TAG_HEAPOBJECT_MASK)); 8794514f5e3Sopenharmony_ci __ And(temp, temp, ret); 8804514f5e3Sopenharmony_ci __ Cmp(temp, Immediate(0)); 8814514f5e3Sopenharmony_ci __ B(Condition::NE, ¬EcmaObject); 8824514f5e3Sopenharmony_ci // acc is heap object 8834514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(ret, TaggedObject::HCLASS_OFFSET)); 8844514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, JSHClass::BIT_FIELD_OFFSET)); 8854514f5e3Sopenharmony_ci __ And(temp.W(), temp.W(), LogicalImmediate::Create(0xFF, RegWSize)); 8864514f5e3Sopenharmony_ci __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_LAST))); 8874514f5e3Sopenharmony_ci __ B(Condition::HI, ¬EcmaObject); 8884514f5e3Sopenharmony_ci __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_FIRST))); 8894514f5e3Sopenharmony_ci __ B(Condition::LO, ¬EcmaObject); 8904514f5e3Sopenharmony_ci // acc is ecma object 8914514f5e3Sopenharmony_ci __ B(&normalReturn); 8924514f5e3Sopenharmony_ci 8934514f5e3Sopenharmony_ci __ Bind(¬EcmaObject); 8944514f5e3Sopenharmony_ci { 8954514f5e3Sopenharmony_ci int64_t funcOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFunctionOffset(false)) - 8964514f5e3Sopenharmony_ci static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 8974514f5e3Sopenharmony_ci ASSERT(funcOffset < 0); 8984514f5e3Sopenharmony_ci __ Ldur(temp, MemoryOperand(currentSp, funcOffset)); // load constructor 8994514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, JSFunctionBase::METHOD_OFFSET)); 9004514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, Method::EXTRA_LITERAL_INFO_OFFSET)); 9014514f5e3Sopenharmony_ci __ Lsr(temp.W(), temp.W(), MethodLiteral::FunctionKindBits::START_BIT); 9024514f5e3Sopenharmony_ci __ And(temp.W(), temp.W(), 9034514f5e3Sopenharmony_ci LogicalImmediate::Create((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1, RegWSize)); 9044514f5e3Sopenharmony_ci __ Cmp(temp.W(), Immediate(static_cast<int64_t>(FunctionKind::CLASS_CONSTRUCTOR))); 9054514f5e3Sopenharmony_ci __ B(Condition::LS, &getThis); // constructor is base 9064514f5e3Sopenharmony_ci // fall through 9074514f5e3Sopenharmony_ci } 9084514f5e3Sopenharmony_ci } 9094514f5e3Sopenharmony_ci } 9104514f5e3Sopenharmony_ci __ Bind(&normalReturn); 9114514f5e3Sopenharmony_ci __ Ret(); 9124514f5e3Sopenharmony_ci} 9134514f5e3Sopenharmony_ci 9144514f5e3Sopenharmony_ci// ResumeCaughtFrameAndDispatch(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool, 9154514f5e3Sopenharmony_ci// uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter) 9164514f5e3Sopenharmony_ci// GHC calling convention 9174514f5e3Sopenharmony_ci// X19 - glue 9184514f5e3Sopenharmony_ci// FP - sp 9194514f5e3Sopenharmony_ci// X20 - pc 9204514f5e3Sopenharmony_ci// X21 - constantPool 9214514f5e3Sopenharmony_ci// X22 - profileTypeInfo 9224514f5e3Sopenharmony_ci// X23 - acc 9234514f5e3Sopenharmony_ci// X24 - hotnessCounter 9244514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler) 9254514f5e3Sopenharmony_ci{ 9264514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ResumeCaughtFrameAndDispatch)); 9274514f5e3Sopenharmony_ci 9284514f5e3Sopenharmony_ci Register glue(X19); 9294514f5e3Sopenharmony_ci Register pc(X20); 9304514f5e3Sopenharmony_ci Register fp(X5); 9314514f5e3Sopenharmony_ci Register opcode(X6, W); 9324514f5e3Sopenharmony_ci Register bcStub(X7); 9334514f5e3Sopenharmony_ci 9344514f5e3Sopenharmony_ci Label dispatch; 9354514f5e3Sopenharmony_ci __ Ldr(fp, MemoryOperand(glue, JSThread::GlueData::GetLastFpOffset(false))); 9364514f5e3Sopenharmony_ci __ Cmp(fp, Immediate(0)); 9374514f5e3Sopenharmony_ci __ B(Condition::EQ, &dispatch); 9384514f5e3Sopenharmony_ci // up frame 9394514f5e3Sopenharmony_ci __ Mov(Register(SP), fp); 9404514f5e3Sopenharmony_ci // fall through 9414514f5e3Sopenharmony_ci __ Bind(&dispatch); 9424514f5e3Sopenharmony_ci { 9434514f5e3Sopenharmony_ci __ Ldrb(opcode, MemoryOperand(pc, 0)); 9444514f5e3Sopenharmony_ci __ Add(bcStub, glue, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2)); 9454514f5e3Sopenharmony_ci __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false))); 9464514f5e3Sopenharmony_ci __ Br(bcStub); 9474514f5e3Sopenharmony_ci } 9484514f5e3Sopenharmony_ci} 9494514f5e3Sopenharmony_ci 9504514f5e3Sopenharmony_ci// ResumeUncaughtFrameAndReturn(uintptr_t glue) 9514514f5e3Sopenharmony_ci// GHC calling convention 9524514f5e3Sopenharmony_ci// X19 - glue 9534514f5e3Sopenharmony_ci// FP - sp 9544514f5e3Sopenharmony_ci// X20 - acc 9554514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler) 9564514f5e3Sopenharmony_ci{ 9574514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ResumeUncaughtFrameAndReturn)); 9584514f5e3Sopenharmony_ci 9594514f5e3Sopenharmony_ci Register glue(X19); 9604514f5e3Sopenharmony_ci Register fp(X5); 9614514f5e3Sopenharmony_ci Register acc(X20); 9624514f5e3Sopenharmony_ci Register cppRet(X0); 9634514f5e3Sopenharmony_ci 9644514f5e3Sopenharmony_ci __ Ldr(fp, MemoryOperand(glue, JSThread::GlueData::GetLastFpOffset(false))); 9654514f5e3Sopenharmony_ci __ Mov(Register(SP), fp); 9664514f5e3Sopenharmony_ci // this method will return to Execute(cpp calling convention), and the return value should be put into X0. 9674514f5e3Sopenharmony_ci __ Mov(cppRet, acc); 9684514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 9694514f5e3Sopenharmony_ci __ Ret(); 9704514f5e3Sopenharmony_ci} 9714514f5e3Sopenharmony_ci 9724514f5e3Sopenharmony_ci// ResumeRspAndRollback(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool, 9734514f5e3Sopenharmony_ci// uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter, size_t jumpSize) 9744514f5e3Sopenharmony_ci// GHC calling convention 9754514f5e3Sopenharmony_ci// X19 - glue 9764514f5e3Sopenharmony_ci// FP - sp 9774514f5e3Sopenharmony_ci// X20 - pc 9784514f5e3Sopenharmony_ci// X21 - constantPool 9794514f5e3Sopenharmony_ci// X22 - profileTypeInfo 9804514f5e3Sopenharmony_ci// X23 - acc 9814514f5e3Sopenharmony_ci// X24 - hotnessCounter 9824514f5e3Sopenharmony_ci// X25 - jumpSizeAfterCall 9834514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndRollback(ExtendedAssembler *assembler) 9844514f5e3Sopenharmony_ci{ 9854514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndRollback)); 9864514f5e3Sopenharmony_ci 9874514f5e3Sopenharmony_ci Register glueRegister = __ GlueRegister(); 9884514f5e3Sopenharmony_ci Register sp(FP); 9894514f5e3Sopenharmony_ci Register rsp(SP); 9904514f5e3Sopenharmony_ci Register pc(X20); 9914514f5e3Sopenharmony_ci Register jumpSizeRegister(X25); 9924514f5e3Sopenharmony_ci 9934514f5e3Sopenharmony_ci Register ret(X23); 9944514f5e3Sopenharmony_ci Register opcode(X6, W); 9954514f5e3Sopenharmony_ci Register bcStub(X7); 9964514f5e3Sopenharmony_ci Register fp(X8); 9974514f5e3Sopenharmony_ci 9984514f5e3Sopenharmony_ci int64_t fpOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false)) 9994514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 10004514f5e3Sopenharmony_ci int64_t spOffset = static_cast<int64_t>(AsmInterpretedFrame::GetBaseOffset(false)) 10014514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 10024514f5e3Sopenharmony_ci int64_t funcOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFunctionOffset(false)) 10034514f5e3Sopenharmony_ci - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false)); 10044514f5e3Sopenharmony_ci ASSERT(fpOffset < 0); 10054514f5e3Sopenharmony_ci ASSERT(spOffset < 0); 10064514f5e3Sopenharmony_ci ASSERT(funcOffset < 0); 10074514f5e3Sopenharmony_ci 10084514f5e3Sopenharmony_ci __ Ldur(fp, MemoryOperand(sp, fpOffset)); // store fp for temporary 10094514f5e3Sopenharmony_ci __ Ldur(ret, MemoryOperand(sp, funcOffset)); // restore acc 10104514f5e3Sopenharmony_ci __ Ldur(sp, MemoryOperand(sp, spOffset)); // update sp 10114514f5e3Sopenharmony_ci 10124514f5e3Sopenharmony_ci __ Add(pc, pc, Operand(jumpSizeRegister, LSL, 0)); 10134514f5e3Sopenharmony_ci __ Ldrb(opcode, MemoryOperand(pc, 0)); 10144514f5e3Sopenharmony_ci 10154514f5e3Sopenharmony_ci __ Mov(rsp, fp); // resume rsp 10164514f5e3Sopenharmony_ci __ Add(bcStub, glueRegister, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2)); 10174514f5e3Sopenharmony_ci __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false))); 10184514f5e3Sopenharmony_ci __ Br(bcStub); 10194514f5e3Sopenharmony_ci} 10204514f5e3Sopenharmony_ci 10214514f5e3Sopenharmony_ci// c++ calling convention 10224514f5e3Sopenharmony_ci// X0 - glue 10234514f5e3Sopenharmony_ci// X1 - callTarget 10244514f5e3Sopenharmony_ci// X2 - method 10254514f5e3Sopenharmony_ci// X3 - callField 10264514f5e3Sopenharmony_ci// X4 - receiver 10274514f5e3Sopenharmony_ci// X5 - value 10284514f5e3Sopenharmony_civoid AsmInterpreterCall::CallGetter(ExtendedAssembler *assembler) 10294514f5e3Sopenharmony_ci{ 10304514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(CallGetter)); 10314514f5e3Sopenharmony_ci Label target; 10324514f5e3Sopenharmony_ci 10334514f5e3Sopenharmony_ci PushAsmInterpBridgeFrame(assembler); 10344514f5e3Sopenharmony_ci __ Bl(&target); 10354514f5e3Sopenharmony_ci PopAsmInterpBridgeFrame(assembler); 10364514f5e3Sopenharmony_ci __ Ret(); 10374514f5e3Sopenharmony_ci __ Bind(&target); 10384514f5e3Sopenharmony_ci { 10394514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_GETTER, FrameTransitionType::OTHER_TO_OTHER); 10404514f5e3Sopenharmony_ci } 10414514f5e3Sopenharmony_ci} 10424514f5e3Sopenharmony_ci 10434514f5e3Sopenharmony_civoid AsmInterpreterCall::CallSetter(ExtendedAssembler *assembler) 10444514f5e3Sopenharmony_ci{ 10454514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(CallSetter)); 10464514f5e3Sopenharmony_ci Label target; 10474514f5e3Sopenharmony_ci PushAsmInterpBridgeFrame(assembler); 10484514f5e3Sopenharmony_ci __ Bl(&target); 10494514f5e3Sopenharmony_ci PopAsmInterpBridgeFrame(assembler); 10504514f5e3Sopenharmony_ci __ Ret(); 10514514f5e3Sopenharmony_ci __ Bind(&target); 10524514f5e3Sopenharmony_ci { 10534514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_SETTER, FrameTransitionType::OTHER_TO_OTHER); 10544514f5e3Sopenharmony_ci } 10554514f5e3Sopenharmony_ci} 10564514f5e3Sopenharmony_ci 10574514f5e3Sopenharmony_civoid AsmInterpreterCall::CallContainersArgs2(ExtendedAssembler *assembler) 10584514f5e3Sopenharmony_ci{ 10594514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(CallContainersArgs2)); 10604514f5e3Sopenharmony_ci Label target; 10614514f5e3Sopenharmony_ci PushAsmInterpBridgeFrame(assembler); 10624514f5e3Sopenharmony_ci __ Bl(&target); 10634514f5e3Sopenharmony_ci PopAsmInterpBridgeFrame(assembler); 10644514f5e3Sopenharmony_ci __ Ret(); 10654514f5e3Sopenharmony_ci __ Bind(&target); 10664514f5e3Sopenharmony_ci { 10674514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG2_WITH_RETURN, 10684514f5e3Sopenharmony_ci FrameTransitionType::OTHER_TO_OTHER); 10694514f5e3Sopenharmony_ci } 10704514f5e3Sopenharmony_ci} 10714514f5e3Sopenharmony_ci 10724514f5e3Sopenharmony_civoid AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler) 10734514f5e3Sopenharmony_ci{ 10744514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(CallContainersArgs3)); 10754514f5e3Sopenharmony_ci Label target; 10764514f5e3Sopenharmony_ci PushAsmInterpBridgeFrame(assembler); 10774514f5e3Sopenharmony_ci __ Bl(&target); 10784514f5e3Sopenharmony_ci PopAsmInterpBridgeFrame(assembler); 10794514f5e3Sopenharmony_ci __ Ret(); 10804514f5e3Sopenharmony_ci __ Bind(&target); 10814514f5e3Sopenharmony_ci { 10824514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG3_WITH_RETURN, 10834514f5e3Sopenharmony_ci FrameTransitionType::OTHER_TO_OTHER); 10844514f5e3Sopenharmony_ci } 10854514f5e3Sopenharmony_ci} 10864514f5e3Sopenharmony_ci 10874514f5e3Sopenharmony_ci// c++ calling convention 10884514f5e3Sopenharmony_ci// X0 - glue 10894514f5e3Sopenharmony_ci// X1 - callTarget 10904514f5e3Sopenharmony_ci// X2 - method 10914514f5e3Sopenharmony_ci// X3 - callField 10924514f5e3Sopenharmony_ci// X4 - arg0(argc) 10934514f5e3Sopenharmony_ci// X5 - arg1(arglist) 10944514f5e3Sopenharmony_ci// X6 - arg3(argthis) 10954514f5e3Sopenharmony_civoid AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler) 10964514f5e3Sopenharmony_ci{ 10974514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(CallReturnWithArgv)); 10984514f5e3Sopenharmony_ci Label target; 10994514f5e3Sopenharmony_ci PushAsmInterpBridgeFrame(assembler); 11004514f5e3Sopenharmony_ci __ Bl(&target); 11014514f5e3Sopenharmony_ci PopAsmInterpBridgeFrame(assembler); 11024514f5e3Sopenharmony_ci __ Ret(); 11034514f5e3Sopenharmony_ci __ Bind(&target); 11044514f5e3Sopenharmony_ci { 11054514f5e3Sopenharmony_ci JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARGV_WITH_RETURN, 11064514f5e3Sopenharmony_ci FrameTransitionType::OTHER_TO_OTHER); 11074514f5e3Sopenharmony_ci } 11084514f5e3Sopenharmony_ci} 11094514f5e3Sopenharmony_ci 11104514f5e3Sopenharmony_ci// preserve all the general registers, except x15 and callee saved registers/ 11114514f5e3Sopenharmony_ci// and call x15 11124514f5e3Sopenharmony_civoid AsmInterpreterCall::PreserveMostCall(ExtendedAssembler* assembler) 11134514f5e3Sopenharmony_ci{ 11144514f5e3Sopenharmony_ci // * layout as the following: 11154514f5e3Sopenharmony_ci // +--------------------------+ --------- 11164514f5e3Sopenharmony_ci // | . . . . . | ^ 11174514f5e3Sopenharmony_ci // callerSP ---> |--------------------------| | 11184514f5e3Sopenharmony_ci // | returnAddr | | 11194514f5e3Sopenharmony_ci // |--------------------------| OptimizedFrame 11204514f5e3Sopenharmony_ci // | callsiteFp | | 11214514f5e3Sopenharmony_ci // fp ---> |--------------------------| | 11224514f5e3Sopenharmony_ci // | OPTIMIZED_FRAME | v 11234514f5e3Sopenharmony_ci // +--------------------------+ --------- 11244514f5e3Sopenharmony_ci // | x0 | 11254514f5e3Sopenharmony_ci // +--------------------------+ 11264514f5e3Sopenharmony_ci // | x1 | 11274514f5e3Sopenharmony_ci // +--------------------------+ 11284514f5e3Sopenharmony_ci // | r2 | 11294514f5e3Sopenharmony_ci // +--------------------------+ 11304514f5e3Sopenharmony_ci // | x3 | 11314514f5e3Sopenharmony_ci // +--------------------------+ 11324514f5e3Sopenharmony_ci // | x4 | 11334514f5e3Sopenharmony_ci // +--------------------------+ 11344514f5e3Sopenharmony_ci // | x5 | 11354514f5e3Sopenharmony_ci // +--------------------------+ 11364514f5e3Sopenharmony_ci // | x6 | 11374514f5e3Sopenharmony_ci // +--------------------------+ 11384514f5e3Sopenharmony_ci // | x7 | 11394514f5e3Sopenharmony_ci // +--------------------------+ 11404514f5e3Sopenharmony_ci // | x8 | 11414514f5e3Sopenharmony_ci // +--------------------------+ 11424514f5e3Sopenharmony_ci // | x9 | 11434514f5e3Sopenharmony_ci // +--------------------------+ 11444514f5e3Sopenharmony_ci // | x10 | 11454514f5e3Sopenharmony_ci // +--------------------------+ 11464514f5e3Sopenharmony_ci // | x11 | 11474514f5e3Sopenharmony_ci // +--------------------------+ 11484514f5e3Sopenharmony_ci // | x12 | 11494514f5e3Sopenharmony_ci // +--------------------------+ 11504514f5e3Sopenharmony_ci // | x13 | 11514514f5e3Sopenharmony_ci // +--------------------------+ 11524514f5e3Sopenharmony_ci // | x14 | 11534514f5e3Sopenharmony_ci // +--------------------------+ 11544514f5e3Sopenharmony_ci // | x16 | 11554514f5e3Sopenharmony_ci // +--------------------------+ 11564514f5e3Sopenharmony_ci // | x17 | 11574514f5e3Sopenharmony_ci // +--------------------------+ 11584514f5e3Sopenharmony_ci // | x18 | 11594514f5e3Sopenharmony_ci // +--------------------------+ 11604514f5e3Sopenharmony_ci // | align | 11614514f5e3Sopenharmony_ci // calleeSP ---> +--------------------------+ 11624514f5e3Sopenharmony_ci { 11634514f5e3Sopenharmony_ci // prologue to save fp, frametype, and update fp. 11644514f5e3Sopenharmony_ci __ Stp(X29, X30, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX)); 11654514f5e3Sopenharmony_ci // Zero register means OPTIMIZED_FRAME 11664514f5e3Sopenharmony_ci __ Stp(X0, Zero, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX)); 11674514f5e3Sopenharmony_ci __ Add(FP, SP, Immediate(DOUBLE_SLOT_SIZE)); 11684514f5e3Sopenharmony_ci } 11694514f5e3Sopenharmony_ci int32_t PreserveRegPairIndex = 9; 11704514f5e3Sopenharmony_ci // x0~x14,x16,x17,x18 should be preserved, 11714514f5e3Sopenharmony_ci // other general registers are callee saved register, callee will save them. 11724514f5e3Sopenharmony_ci __ Sub(SP, SP, Immediate(DOUBLE_SLOT_SIZE * PreserveRegPairIndex)); 11734514f5e3Sopenharmony_ci __ Stp(X1, X2, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11744514f5e3Sopenharmony_ci __ Stp(X3, X4, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11754514f5e3Sopenharmony_ci __ Stp(X5, X6, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11764514f5e3Sopenharmony_ci __ Stp(X7, X8, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11774514f5e3Sopenharmony_ci __ Stp(X9, X10, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11784514f5e3Sopenharmony_ci __ Stp(X11, X12, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11794514f5e3Sopenharmony_ci __ Stp(X13, X14, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11804514f5e3Sopenharmony_ci __ Stp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex))); 11814514f5e3Sopenharmony_ci __ Str(X18, MemoryOperand(SP, FRAME_SLOT_SIZE)); 11824514f5e3Sopenharmony_ci __ Blr(X15); 11834514f5e3Sopenharmony_ci __ Ldr(X18, MemoryOperand(SP, FRAME_SLOT_SIZE)); 11844514f5e3Sopenharmony_ci __ Ldp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11854514f5e3Sopenharmony_ci __ Ldp(X13, X14, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11864514f5e3Sopenharmony_ci __ Ldp(X11, X12, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11874514f5e3Sopenharmony_ci __ Ldp(X9, X10, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11884514f5e3Sopenharmony_ci __ Ldp(X7, X8, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11894514f5e3Sopenharmony_ci __ Ldp(X5, X6, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11904514f5e3Sopenharmony_ci __ Ldp(X3, X4, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11914514f5e3Sopenharmony_ci __ Ldp(X1, X2, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++))); 11924514f5e3Sopenharmony_ci __ Ldr(X0, MemoryOperand(SP, DOUBLE_SLOT_SIZE * PreserveRegPairIndex)); 11934514f5e3Sopenharmony_ci { 11944514f5e3Sopenharmony_ci // epilogue to restore sp, fp, lr. 11954514f5e3Sopenharmony_ci // Skip x0 slot and frametype slot 11964514f5e3Sopenharmony_ci __ Add(SP, SP, Immediate(DOUBLE_SLOT_SIZE * PreserveRegPairIndex + 11974514f5e3Sopenharmony_ci FRAME_SLOT_SIZE + FRAME_SLOT_SIZE)); 11984514f5e3Sopenharmony_ci __ Ldp(FP, X30, MemoryOperand(SP, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX)); 11994514f5e3Sopenharmony_ci __ Ret(); 12004514f5e3Sopenharmony_ci } 12014514f5e3Sopenharmony_ci} 12024514f5e3Sopenharmony_ci 12034514f5e3Sopenharmony_ci// ASMFastWriteBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value) 12044514f5e3Sopenharmony_ci// c calling convention, but preserve all general registers except %x15 12054514f5e3Sopenharmony_ci// %x0 - glue 12064514f5e3Sopenharmony_ci// %x1 - obj 12074514f5e3Sopenharmony_ci// %x2 - offset 12084514f5e3Sopenharmony_ci// %x3 - value 12094514f5e3Sopenharmony_civoid AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler) 12104514f5e3Sopenharmony_ci{ 12114514f5e3Sopenharmony_ci // valid region flag are as follows, assume it will be ALWAYS VALID. 12124514f5e3Sopenharmony_ci // Judge the region of value with: 12134514f5e3Sopenharmony_ci // "young" "sweepable share" "readonly share" 12144514f5e3Sopenharmony_ci // region flag: 0x08, 0x09, [0x0A, 0x11], [0x12, 0x15], 0x16 12154514f5e3Sopenharmony_ci // value is share: [0x12, 0x16] => valueMaybeSweepableShare 12164514f5e3Sopenharmony_ci // readonly share: 0x16 => return 12174514f5e3Sopenharmony_ci // sweepable share: [0x12, 0x15] => needShareBarrier 12184514f5e3Sopenharmony_ci // value is not share: 0x08, 0x09, [0x0A, 0x11], => valueNotShare 12194514f5e3Sopenharmony_ci // value is young : 0x09 => needCallNotShare 12204514f5e3Sopenharmony_ci // value is not young : 0x08, [0x0A, 0x11], => checkMark 12214514f5e3Sopenharmony_ci ASSERT(GENERAL_YOUNG_BEGIN <= IN_YOUNG_SPACE && IN_YOUNG_SPACE < SHARED_SPACE_BEGIN && 12224514f5e3Sopenharmony_ci SHARED_SPACE_BEGIN <= SHARED_SWEEPABLE_SPACE_BEGIN && SHARED_SWEEPABLE_SPACE_END < IN_SHARED_READ_ONLY_SPACE && 12234514f5e3Sopenharmony_ci IN_SHARED_READ_ONLY_SPACE == HEAP_SPACE_END); 12244514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ASMFastWriteBarrier)); 12254514f5e3Sopenharmony_ci Label needCall; 12264514f5e3Sopenharmony_ci Label checkMark; 12274514f5e3Sopenharmony_ci Label needCallNotShare; 12284514f5e3Sopenharmony_ci Label needShareBarrier; 12294514f5e3Sopenharmony_ci Label valueNotShare; 12304514f5e3Sopenharmony_ci Label valueMaybeSweepableShare; 12314514f5e3Sopenharmony_ci { 12324514f5e3Sopenharmony_ci // int8_t *valueRegion = value & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK)) 12334514f5e3Sopenharmony_ci // int8_t valueFlag = *valueRegion 12344514f5e3Sopenharmony_ci // if (valueFlag >= SHARED_SWEEPABLE_SPACE_BEGIN){ 12354514f5e3Sopenharmony_ci // goto valueMaybeSweepableShare 12364514f5e3Sopenharmony_ci // } 12374514f5e3Sopenharmony_ci 12384514f5e3Sopenharmony_ci __ And(X15, X3, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize)); 12394514f5e3Sopenharmony_ci // X15 is the region address of value. 12404514f5e3Sopenharmony_ci __ Ldrb(Register(X15, W), MemoryOperand(X15, 0)); 12414514f5e3Sopenharmony_ci // X15 is the flag load from region of value. 12424514f5e3Sopenharmony_ci __ Cmp(Register(X15, W), Immediate(SHARED_SWEEPABLE_SPACE_BEGIN)); 12434514f5e3Sopenharmony_ci __ B(GE, &valueMaybeSweepableShare); 12444514f5e3Sopenharmony_ci // if value may be SweepableShare, goto valueMaybeSweepableShare 12454514f5e3Sopenharmony_ci } 12464514f5e3Sopenharmony_ci __ Bind(&valueNotShare); 12474514f5e3Sopenharmony_ci { 12484514f5e3Sopenharmony_ci // valueNotShare: 12494514f5e3Sopenharmony_ci // if (valueFlag != IN_YOUNG_SPACE){ 12504514f5e3Sopenharmony_ci // goto checkMark 12514514f5e3Sopenharmony_ci // } 12524514f5e3Sopenharmony_ci // int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK)) 12534514f5e3Sopenharmony_ci // int8_t objFlag = *objRegion 12544514f5e3Sopenharmony_ci // if (objFlag != IN_YOUNG_SPACE){ 12554514f5e3Sopenharmony_ci // goto needCallNotShare 12564514f5e3Sopenharmony_ci // } 12574514f5e3Sopenharmony_ci 12584514f5e3Sopenharmony_ci __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_YOUNG_SPACE)); 12594514f5e3Sopenharmony_ci __ B(NE, &checkMark); 12604514f5e3Sopenharmony_ci // if value is not in young, goto checkMark 12614514f5e3Sopenharmony_ci 12624514f5e3Sopenharmony_ci __ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize)); 12634514f5e3Sopenharmony_ci // X15 is the region address of obj. 12644514f5e3Sopenharmony_ci __ Ldrb(Register(X15, W), MemoryOperand(X15, 0)); 12654514f5e3Sopenharmony_ci // X15 is the flag load from region of obj. 12664514f5e3Sopenharmony_ci __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_YOUNG_SPACE)); 12674514f5e3Sopenharmony_ci __ B(NE, &needCallNotShare); 12684514f5e3Sopenharmony_ci // if obj is not in young, goto needCallNotShare 12694514f5e3Sopenharmony_ci } 12704514f5e3Sopenharmony_ci 12714514f5e3Sopenharmony_ci __ Bind(&checkMark); 12724514f5e3Sopenharmony_ci { 12734514f5e3Sopenharmony_ci // checkMark: 12744514f5e3Sopenharmony_ci // int8_t GCStateBitField = *(glue+GCStateBitFieldOffset) 12754514f5e3Sopenharmony_ci // if (GCStateBitField & JSThread::CONCURRENT_MARKING_BITFIELD_MASK != 0) { 12764514f5e3Sopenharmony_ci // goto needCallNotShare 12774514f5e3Sopenharmony_ci // } 12784514f5e3Sopenharmony_ci // return 12794514f5e3Sopenharmony_ci 12804514f5e3Sopenharmony_ci __ Mov(X15, JSThread::GlueData::GetGCStateBitFieldOffset(false)); 12814514f5e3Sopenharmony_ci __ Ldrb(Register(X15, W), MemoryOperand(X0, Register(X15), UXTX)); 12824514f5e3Sopenharmony_ci __ Tst(Register(X15, W), LogicalImmediate::Create(JSThread::CONCURRENT_MARKING_BITFIELD_MASK, RegWSize)); 12834514f5e3Sopenharmony_ci __ B(NE, &needCallNotShare); 12844514f5e3Sopenharmony_ci // if GCState is not READY_TO_MARK, go to needCallNotShare. 12854514f5e3Sopenharmony_ci __ Ret(); 12864514f5e3Sopenharmony_ci } 12874514f5e3Sopenharmony_ci 12884514f5e3Sopenharmony_ci __ Bind(&valueMaybeSweepableShare); 12894514f5e3Sopenharmony_ci { 12904514f5e3Sopenharmony_ci // valueMaybeSweepableShare: 12914514f5e3Sopenharmony_ci // if (valueFlag != IN_SHARED_READ_ONLY_SPACE){ 12924514f5e3Sopenharmony_ci // goto needShareBarrier 12934514f5e3Sopenharmony_ci // } 12944514f5e3Sopenharmony_ci // return 12954514f5e3Sopenharmony_ci __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_SHARED_READ_ONLY_SPACE)); 12964514f5e3Sopenharmony_ci __ B(NE, &needShareBarrier); 12974514f5e3Sopenharmony_ci __ Ret(); 12984514f5e3Sopenharmony_ci } 12994514f5e3Sopenharmony_ci 13004514f5e3Sopenharmony_ci __ Bind(&needCallNotShare); 13014514f5e3Sopenharmony_ci { 13024514f5e3Sopenharmony_ci int32_t NonSValueBarrier = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) + 13034514f5e3Sopenharmony_ci kungfu::CommonStubCSigns::SetNonSValueWithBarrier * FRAME_SLOT_SIZE; 13044514f5e3Sopenharmony_ci __ Mov(X15, NonSValueBarrier); 13054514f5e3Sopenharmony_ci } 13064514f5e3Sopenharmony_ci __ Bind(&needCall); 13074514f5e3Sopenharmony_ci { 13084514f5e3Sopenharmony_ci __ Ldr(X15, MemoryOperand(X0, Register(X15), UXTX)); 13094514f5e3Sopenharmony_ci PreserveMostCall(assembler); 13104514f5e3Sopenharmony_ci } 13114514f5e3Sopenharmony_ci __ Bind(&needShareBarrier); 13124514f5e3Sopenharmony_ci { 13134514f5e3Sopenharmony_ci ASMFastSharedWriteBarrier(assembler, needCall); 13144514f5e3Sopenharmony_ci } 13154514f5e3Sopenharmony_ci} 13164514f5e3Sopenharmony_ci 13174514f5e3Sopenharmony_ci// ASMWriteBarrierWithEden(GateRef glue, GateRef obj, GateRef offset, GateRef value) 13184514f5e3Sopenharmony_ci// c calling convention, but preserve all general registers except %x15 13194514f5e3Sopenharmony_ci// %x0 - glue 13204514f5e3Sopenharmony_ci// %x1 - obj 13214514f5e3Sopenharmony_ci// %x2 - offset 13224514f5e3Sopenharmony_ci// %x3 - value 13234514f5e3Sopenharmony_civoid AsmInterpreterCall::ASMWriteBarrierWithEden(ExtendedAssembler* assembler) 13244514f5e3Sopenharmony_ci{ 13254514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(ASMWriteBarrierWithEden)); 13264514f5e3Sopenharmony_ci // Just for compitability, not a fast implement, should be refactored when enable EdenBarrier. 13274514f5e3Sopenharmony_ci int32_t EdenBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) + 13284514f5e3Sopenharmony_ci kungfu::CommonStubCSigns::SetValueWithEdenBarrier * FRAME_SLOT_SIZE; 13294514f5e3Sopenharmony_ci __ Mov(X15, EdenBarrierOffset); 13304514f5e3Sopenharmony_ci __ Ldr(X15, MemoryOperand(X0, Register(X15), UXTX)); 13314514f5e3Sopenharmony_ci PreserveMostCall(assembler); 13324514f5e3Sopenharmony_ci} 13334514f5e3Sopenharmony_ci 13344514f5e3Sopenharmony_ci// %x0 - glue 13354514f5e3Sopenharmony_ci// %x1 - obj 13364514f5e3Sopenharmony_ci// %x2 - offset 13374514f5e3Sopenharmony_ci// %x3 - value 13384514f5e3Sopenharmony_civoid AsmInterpreterCall::ASMFastSharedWriteBarrier(ExtendedAssembler* assembler, Label& needCall) 13394514f5e3Sopenharmony_ci{ 13404514f5e3Sopenharmony_ci Label checkBarrierForSharedValue; 13414514f5e3Sopenharmony_ci Label restoreScratchRegister; 13424514f5e3Sopenharmony_ci Label callSharedBarrier; 13434514f5e3Sopenharmony_ci { 13444514f5e3Sopenharmony_ci // int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK)) 13454514f5e3Sopenharmony_ci // int8_t objFlag = *objRegion 13464514f5e3Sopenharmony_ci // if (objFlag >= SHARED_SPACE_BEGIN){ 13474514f5e3Sopenharmony_ci // // share to share, just check the barrier 13484514f5e3Sopenharmony_ci // goto checkBarrierForSharedValue 13494514f5e3Sopenharmony_ci // } 13504514f5e3Sopenharmony_ci __ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize)); 13514514f5e3Sopenharmony_ci __ Ldrb(Register(X15, W), MemoryOperand(X15, 0)); 13524514f5e3Sopenharmony_ci // X15 is the flag load from region of obj. 13534514f5e3Sopenharmony_ci __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::SHARED_SPACE_BEGIN)); 13544514f5e3Sopenharmony_ci __ B(GE, &checkBarrierForSharedValue); // if objflag >= SHARED_SPACE_BEGIN => checkBarrierForSharedValue 13554514f5e3Sopenharmony_ci } 13564514f5e3Sopenharmony_ci { 13574514f5e3Sopenharmony_ci // int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK)) 13584514f5e3Sopenharmony_ci // int8_t *localToShareSet = *(objRegion + LocalToShareSetOffset) 13594514f5e3Sopenharmony_ci // if (localToShareSet == 0){ 13604514f5e3Sopenharmony_ci // goto callSharedBarrier 13614514f5e3Sopenharmony_ci // } 13624514f5e3Sopenharmony_ci __ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize)); 13634514f5e3Sopenharmony_ci __ Ldr(X15, MemoryOperand(X15, Region::PackedData::GetLocalToShareSetOffset(false))); 13644514f5e3Sopenharmony_ci // X15 is localToShareSet for obj region. 13654514f5e3Sopenharmony_ci __ Cbz({X15, X}, &callSharedBarrier); // if localToShareSet == 0 => callSharedBarrier 13664514f5e3Sopenharmony_ci } 13674514f5e3Sopenharmony_ci { 13684514f5e3Sopenharmony_ci // X16, X17 will be used as scratch register, spill them. 13694514f5e3Sopenharmony_ci // the caller will call this function with inline asm, it will not save any registers except x15. 13704514f5e3Sopenharmony_ci // So we need spill and restore x16, x17 when we need them as scratch register. 13714514f5e3Sopenharmony_ci { 13724514f5e3Sopenharmony_ci __ Stp(X16, X17, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX)); 13734514f5e3Sopenharmony_ci } 13744514f5e3Sopenharmony_ci // int64_t objOffset = obj & DEFAULT_REGION_MASK 13754514f5e3Sopenharmony_ci // int64_t slotOffset = objOffset + offset 13764514f5e3Sopenharmony_ci __ And(X16, X1, LogicalImmediate::Create(DEFAULT_REGION_MASK, RegXSize)); 13774514f5e3Sopenharmony_ci __ Add(X16, X16, Operand(Register(X2))); 13784514f5e3Sopenharmony_ci 13794514f5e3Sopenharmony_ci // the logic to get mask in stub_builder.cpp 13804514f5e3Sopenharmony_ci // [63-------------------------35][34------------------------8][7---3][2-0] 13814514f5e3Sopenharmony_ci // bitOffset: bbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc 13824514f5e3Sopenharmony_ci // bitPerWordMask: 11 111 13834514f5e3Sopenharmony_ci // indexInWord = And bitoffset bitPerWordMask 13844514f5e3Sopenharmony_ci // indexInWord: cc ccc 13854514f5e3Sopenharmony_ci // mask = 1 << indexInWord 13864514f5e3Sopenharmony_ci 13874514f5e3Sopenharmony_ci // the logic to test bit set value here: 13884514f5e3Sopenharmony_ci // [63-------------------------35][34------------------------8][7---3][2-0] 13894514f5e3Sopenharmony_ci // slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd 13904514f5e3Sopenharmony_ci // Ubfm X16 slotOffset 3 7 13914514f5e3Sopenharmony_ci // indexInWord: cc ccc 13924514f5e3Sopenharmony_ci __ Ubfm(X17, X16, TAGGED_TYPE_SIZE_LOG, TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2 - 1); 13934514f5e3Sopenharmony_ci 13944514f5e3Sopenharmony_ci // the logic to get byteIndex in stub_builder.cpp 13954514f5e3Sopenharmony_ci // [63-------------------------35][34------------------------8][7---3][2-0] 13964514f5e3Sopenharmony_ci // slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd 13974514f5e3Sopenharmony_ci // 1. bitOffsetPtr = LSR TAGGED_TYPE_SIZE_LOG(3) slotOffset 13984514f5e3Sopenharmony_ci // bitOffsetPtr: aaaaaaaaaaaaaaaaaaaaaaaaaa aaabbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc 13994514f5e3Sopenharmony_ci // 2. bitOffset = TruncPtrToInt32 bitOffsetPtr 14004514f5e3Sopenharmony_ci // bitOffset: bbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc 14014514f5e3Sopenharmony_ci // 3. index = LSR BIT_PER_WORD_LOG2(5) bitOffset 14024514f5e3Sopenharmony_ci // index: bbbbbbbbbbbbbbbbbbb bbbbb bbb 14034514f5e3Sopenharmony_ci // 4. byteIndex = Mul index BYTE_PER_WORD(4) 14044514f5e3Sopenharmony_ci // byteIndex: bbbbbbbbbbbbbbbbbbbbb bbbbb b00 14054514f5e3Sopenharmony_ci 14064514f5e3Sopenharmony_ci // the logic to get byteIndex here: 14074514f5e3Sopenharmony_ci // [63-------------------------35][34------------------------8][7---3][2-0] 14084514f5e3Sopenharmony_ci // slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd 14094514f5e3Sopenharmony_ci // Ubfm X16 slotOffset 8 34 14104514f5e3Sopenharmony_ci // index: bbbbbbbbbbbbbbbbbbb bbbbb bbb 14114514f5e3Sopenharmony_ci __ Ubfm(X16, X16, TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2, 14124514f5e3Sopenharmony_ci sizeof(uint32_t) * GCBitset::BIT_PER_BYTE + TAGGED_TYPE_SIZE_LOG - 1); 14134514f5e3Sopenharmony_ci __ Add(X15, X15, Operand(Register(X16), LSL, GCBitset::BYTE_PER_WORD_LOG2)); 14144514f5e3Sopenharmony_ci __ Add(X15, X15, Immediate(RememberedSet::GCBITSET_DATA_OFFSET)); 14154514f5e3Sopenharmony_ci // X15 is the address of bitset value. X15 = X15 + X16 << BYTE_PER_WORD_LOG2 + GCBITSET_DATA_OFFSET 14164514f5e3Sopenharmony_ci 14174514f5e3Sopenharmony_ci // mask = 1 << indexInWord 14184514f5e3Sopenharmony_ci __ Mov(Register(X16, W), 1); 14194514f5e3Sopenharmony_ci __ Lsl(Register(X17, W), Register(X16, W), Register(X17, W)); // X17 is the mask 14204514f5e3Sopenharmony_ci 14214514f5e3Sopenharmony_ci __ Ldr(Register(X16, W), MemoryOperand(X15, 0)); // x16: oldsetValue 14224514f5e3Sopenharmony_ci __ Tst(Register(X16, W), Register(X17, W)); 14234514f5e3Sopenharmony_ci __ B(NE, &restoreScratchRegister); 14244514f5e3Sopenharmony_ci __ Orr(Register(X16, W), Register(X16, W), Register(X17, W)); 14254514f5e3Sopenharmony_ci __ Str(Register(X16, W), MemoryOperand(X15, 0)); 14264514f5e3Sopenharmony_ci } 14274514f5e3Sopenharmony_ci __ Bind(&restoreScratchRegister); 14284514f5e3Sopenharmony_ci { 14294514f5e3Sopenharmony_ci __ Ldp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE, POSTINDEX)); 14304514f5e3Sopenharmony_ci } 14314514f5e3Sopenharmony_ci __ Bind(&checkBarrierForSharedValue); 14324514f5e3Sopenharmony_ci { 14334514f5e3Sopenharmony_ci // checkBarrierForSharedValue: 14344514f5e3Sopenharmony_ci // int8_t GCStateBitField = *(glue+SharedGCStateBitFieldOffset) 14354514f5e3Sopenharmony_ci // if (GCStateBitField & JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK != 0) { 14364514f5e3Sopenharmony_ci // goto callSharedBarrier 14374514f5e3Sopenharmony_ci // } 14384514f5e3Sopenharmony_ci // return 14394514f5e3Sopenharmony_ci __ Mov(X15, JSThread::GlueData::GetSharedGCStateBitFieldOffset(false)); 14404514f5e3Sopenharmony_ci __ Ldrb(Register(X15, W), MemoryOperand(X0, Register(X15), UXTX)); 14414514f5e3Sopenharmony_ci static_assert(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK == 1 && "Tbnz can't handle other bit mask"); 14424514f5e3Sopenharmony_ci __ Tbnz(Register(X15, W), 0, &callSharedBarrier); 14434514f5e3Sopenharmony_ci // if GCState is not READY_TO_MARK, go to needCallNotShare. 14444514f5e3Sopenharmony_ci __ Ret(); 14454514f5e3Sopenharmony_ci } 14464514f5e3Sopenharmony_ci 14474514f5e3Sopenharmony_ci __ Bind(&callSharedBarrier); 14484514f5e3Sopenharmony_ci { 14494514f5e3Sopenharmony_ci int32_t SValueBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) + 14504514f5e3Sopenharmony_ci kungfu::CommonStubCSigns::SetSValueWithBarrier * FRAME_SLOT_SIZE; 14514514f5e3Sopenharmony_ci __ Mov(X15, SValueBarrierOffset); 14524514f5e3Sopenharmony_ci __ B(&needCall); 14534514f5e3Sopenharmony_ci } 14544514f5e3Sopenharmony_ci} 14554514f5e3Sopenharmony_ci 14564514f5e3Sopenharmony_ci// Generate code for generator re-entering asm interpreter 14574514f5e3Sopenharmony_ci// c++ calling convention 14584514f5e3Sopenharmony_ci// Input: %X0 - glue 14594514f5e3Sopenharmony_ci// %X1 - context(GeneratorContext) 14604514f5e3Sopenharmony_civoid AsmInterpreterCall::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler) 14614514f5e3Sopenharmony_ci{ 14624514f5e3Sopenharmony_ci __ BindAssemblerStub(RTSTUB_ID(GeneratorReEnterAsmInterp)); 14634514f5e3Sopenharmony_ci Label target; 14644514f5e3Sopenharmony_ci size_t begin = __ GetCurrentPosition(); 14654514f5e3Sopenharmony_ci PushAsmInterpEntryFrame(assembler); 14664514f5e3Sopenharmony_ci __ Bl(&target); 14674514f5e3Sopenharmony_ci PopAsmInterpEntryFrame(assembler); 14684514f5e3Sopenharmony_ci size_t end = __ GetCurrentPosition(); 14694514f5e3Sopenharmony_ci if ((end - begin) != FrameCompletionPos::ARM64EntryFrameDuration) { 14704514f5e3Sopenharmony_ci LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64EntryFrameDuration 14714514f5e3Sopenharmony_ci << "This frame has been modified, and the offset EntryFrameDuration should be updated too."; 14724514f5e3Sopenharmony_ci } 14734514f5e3Sopenharmony_ci __ Ret(); 14744514f5e3Sopenharmony_ci __ Bind(&target); 14754514f5e3Sopenharmony_ci { 14764514f5e3Sopenharmony_ci GeneratorReEnterAsmInterpDispatch(assembler); 14774514f5e3Sopenharmony_ci } 14784514f5e3Sopenharmony_ci} 14794514f5e3Sopenharmony_ci 14804514f5e3Sopenharmony_civoid AsmInterpreterCall::GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler) 14814514f5e3Sopenharmony_ci{ 14824514f5e3Sopenharmony_ci Label pushFrameState; 14834514f5e3Sopenharmony_ci Label stackOverflow; 14844514f5e3Sopenharmony_ci Register glue = __ GlueRegister(); 14854514f5e3Sopenharmony_ci Register contextRegister(X1); 14864514f5e3Sopenharmony_ci Register spRegister(SP); 14874514f5e3Sopenharmony_ci Register pc(X8); 14884514f5e3Sopenharmony_ci Register prevSpRegister(FP); 14894514f5e3Sopenharmony_ci Register callTarget(X4); 14904514f5e3Sopenharmony_ci Register method(X5); 14914514f5e3Sopenharmony_ci Register temp(X6); // can not be used to store any variable 14924514f5e3Sopenharmony_ci Register currentSlotRegister(X7); 14934514f5e3Sopenharmony_ci Register fpRegister(X9); 14944514f5e3Sopenharmony_ci Register thisRegister(X25); 14954514f5e3Sopenharmony_ci Register nRegsRegister(X26, W); 14964514f5e3Sopenharmony_ci Register regsArrayRegister(X27); 14974514f5e3Sopenharmony_ci Register newSp(X28); 14984514f5e3Sopenharmony_ci __ Ldr(callTarget, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_METHOD_OFFSET)); 14994514f5e3Sopenharmony_ci __ Ldr(method, MemoryOperand(callTarget, JSFunctionBase::METHOD_OFFSET)); 15004514f5e3Sopenharmony_ci __ PushFpAndLr(); 15014514f5e3Sopenharmony_ci // save fp 15024514f5e3Sopenharmony_ci __ Mov(fpRegister, spRegister); 15034514f5e3Sopenharmony_ci __ Mov(currentSlotRegister, spRegister); 15044514f5e3Sopenharmony_ci // Reserve enough sp space to prevent stack parameters from being covered by cpu profiler. 15054514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false))); 15064514f5e3Sopenharmony_ci __ Mov(Register(SP), temp); 15074514f5e3Sopenharmony_ci // push context regs 15084514f5e3Sopenharmony_ci __ Ldr(nRegsRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET)); 15094514f5e3Sopenharmony_ci __ Ldr(thisRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_THIS_OFFSET)); 15104514f5e3Sopenharmony_ci __ Ldr(regsArrayRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET)); 15114514f5e3Sopenharmony_ci __ Add(regsArrayRegister, regsArrayRegister, Immediate(TaggedArray::DATA_OFFSET)); 15124514f5e3Sopenharmony_ci PushArgsWithArgv(assembler, glue, nRegsRegister, regsArrayRegister, temp, 15134514f5e3Sopenharmony_ci currentSlotRegister, &pushFrameState, &stackOverflow); 15144514f5e3Sopenharmony_ci 15154514f5e3Sopenharmony_ci __ Bind(&pushFrameState); 15164514f5e3Sopenharmony_ci __ Mov(newSp, currentSlotRegister); 15174514f5e3Sopenharmony_ci // push frame state 15184514f5e3Sopenharmony_ci PushGeneratorFrameState(assembler, prevSpRegister, fpRegister, currentSlotRegister, callTarget, thisRegister, 15194514f5e3Sopenharmony_ci method, contextRegister, pc, temp); 15204514f5e3Sopenharmony_ci __ Align16(currentSlotRegister); 15214514f5e3Sopenharmony_ci __ Mov(Register(SP), currentSlotRegister); 15224514f5e3Sopenharmony_ci // call bc stub 15234514f5e3Sopenharmony_ci CallBCStub(assembler, newSp, glue, callTarget, method, pc, temp); 15244514f5e3Sopenharmony_ci 15254514f5e3Sopenharmony_ci __ Bind(&stackOverflow); 15264514f5e3Sopenharmony_ci { 15274514f5e3Sopenharmony_ci ThrowStackOverflowExceptionAndReturn(assembler, glue, fpRegister, temp); 15284514f5e3Sopenharmony_ci } 15294514f5e3Sopenharmony_ci} 15304514f5e3Sopenharmony_ci 15314514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThis(ExtendedAssembler *assembler, 15324514f5e3Sopenharmony_ci JSCallMode mode, Label *stackOverflow, FrameTransitionType type) 15334514f5e3Sopenharmony_ci{ 15344514f5e3Sopenharmony_ci Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); 15354514f5e3Sopenharmony_ci Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); 15364514f5e3Sopenharmony_ci Register thisRegister = __ AvailableRegister2(); 15374514f5e3Sopenharmony_ci Register currentSlotRegister = __ AvailableRegister3(); 15384514f5e3Sopenharmony_ci 15394514f5e3Sopenharmony_ci Label pushVregs; 15404514f5e3Sopenharmony_ci Label pushNewTarget; 15414514f5e3Sopenharmony_ci Label pushCallTarget; 15424514f5e3Sopenharmony_ci bool haveThis = kungfu::AssemblerModule::JSModeHaveThisArg(mode); 15434514f5e3Sopenharmony_ci bool haveNewTarget = kungfu::AssemblerModule::JSModeHaveNewTargetArg(mode); 15444514f5e3Sopenharmony_ci if (!haveThis) { 15454514f5e3Sopenharmony_ci __ Mov(thisRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED)); // default this: undefined 15464514f5e3Sopenharmony_ci } else { 15474514f5e3Sopenharmony_ci Register thisArgRegister = GetThisRegsiter(assembler, mode, thisRegister); 15484514f5e3Sopenharmony_ci if (thisRegister.GetId() != thisArgRegister.GetId()) { 15494514f5e3Sopenharmony_ci __ Mov(thisRegister, thisArgRegister); 15504514f5e3Sopenharmony_ci } 15514514f5e3Sopenharmony_ci } 15524514f5e3Sopenharmony_ci __ Tst(callFieldRegister, LogicalImmediate::Create(CALL_TYPE_MASK, RegXSize)); 15534514f5e3Sopenharmony_ci __ B(Condition::EQ, &pushVregs); 15544514f5e3Sopenharmony_ci __ Tbz(callFieldRegister, MethodLiteral::HaveThisBit::START_BIT, &pushNewTarget); 15554514f5e3Sopenharmony_ci if (!haveThis) { 15564514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 15574514f5e3Sopenharmony_ci Register tempRegister = __ TempRegister1(); 15584514f5e3Sopenharmony_ci __ Mov(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 15594514f5e3Sopenharmony_ci __ Str(tempRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 15604514f5e3Sopenharmony_ci } else { 15614514f5e3Sopenharmony_ci __ Str(thisRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 15624514f5e3Sopenharmony_ci } 15634514f5e3Sopenharmony_ci __ Bind(&pushNewTarget); 15644514f5e3Sopenharmony_ci { 15654514f5e3Sopenharmony_ci __ Tbz(callFieldRegister, MethodLiteral::HaveNewTargetBit::START_BIT, &pushCallTarget); 15664514f5e3Sopenharmony_ci if (!haveNewTarget) { 15674514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 15684514f5e3Sopenharmony_ci Register newTarget = __ TempRegister1(); 15694514f5e3Sopenharmony_ci __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 15704514f5e3Sopenharmony_ci __ Str(newTarget, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 15714514f5e3Sopenharmony_ci } else { 15724514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 15734514f5e3Sopenharmony_ci Register defaultRegister = __ TempRegister1(); 15744514f5e3Sopenharmony_ci Register newTargetRegister = GetNewTargetRegsiter(assembler, mode, defaultRegister); 15754514f5e3Sopenharmony_ci __ Str(newTargetRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 15764514f5e3Sopenharmony_ci } 15774514f5e3Sopenharmony_ci } 15784514f5e3Sopenharmony_ci __ Bind(&pushCallTarget); 15794514f5e3Sopenharmony_ci { 15804514f5e3Sopenharmony_ci __ Tbz(callFieldRegister, MethodLiteral::HaveFuncBit::START_BIT, &pushVregs); 15814514f5e3Sopenharmony_ci __ Str(callTargetRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 15824514f5e3Sopenharmony_ci } 15834514f5e3Sopenharmony_ci __ Bind(&pushVregs); 15844514f5e3Sopenharmony_ci { 15854514f5e3Sopenharmony_ci PushVregs(assembler, stackOverflow, type); 15864514f5e3Sopenharmony_ci } 15874514f5e3Sopenharmony_ci} 15884514f5e3Sopenharmony_ci 15894514f5e3Sopenharmony_civoid AsmInterpreterCall::PushVregs(ExtendedAssembler *assembler, 15904514f5e3Sopenharmony_ci Label *stackOverflow, FrameTransitionType type) 15914514f5e3Sopenharmony_ci{ 15924514f5e3Sopenharmony_ci Register glue = __ GlueRegister(); 15934514f5e3Sopenharmony_ci Register prevSpRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::SP); 15944514f5e3Sopenharmony_ci Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); 15954514f5e3Sopenharmony_ci Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD); 15964514f5e3Sopenharmony_ci Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); 15974514f5e3Sopenharmony_ci Register fpRegister = __ AvailableRegister1(); 15984514f5e3Sopenharmony_ci Register thisRegister = __ AvailableRegister2(); 15994514f5e3Sopenharmony_ci Register currentSlotRegister = __ AvailableRegister3(); 16004514f5e3Sopenharmony_ci 16014514f5e3Sopenharmony_ci Label pushFrameStateAndCall; 16024514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 16034514f5e3Sopenharmony_ci Register tempRegister = __ TempRegister1(); 16044514f5e3Sopenharmony_ci // args register can be reused now. 16054514f5e3Sopenharmony_ci Register newSpRegister = __ AvailableRegister4(); 16064514f5e3Sopenharmony_ci Register numVregsRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); 16074514f5e3Sopenharmony_ci GetNumVregsFromCallField(assembler, callFieldRegister, numVregsRegister); 16084514f5e3Sopenharmony_ci PushUndefinedWithArgc(assembler, glue, numVregsRegister, tempRegister, currentSlotRegister, &pushFrameStateAndCall, 16094514f5e3Sopenharmony_ci stackOverflow); 16104514f5e3Sopenharmony_ci // fall through 16114514f5e3Sopenharmony_ci __ Bind(&pushFrameStateAndCall); 16124514f5e3Sopenharmony_ci { 16134514f5e3Sopenharmony_ci __ Mov(newSpRegister, currentSlotRegister); 16144514f5e3Sopenharmony_ci 16154514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister2Scope scope2(assembler); 16164514f5e3Sopenharmony_ci Register pcRegister = __ TempRegister2(); 16174514f5e3Sopenharmony_ci PushFrameState(assembler, prevSpRegister, fpRegister, currentSlotRegister, callTargetRegister, thisRegister, 16184514f5e3Sopenharmony_ci methodRegister, pcRegister, tempRegister); 16194514f5e3Sopenharmony_ci 16204514f5e3Sopenharmony_ci __ Align16(currentSlotRegister); 16214514f5e3Sopenharmony_ci __ Mov(Register(SP), currentSlotRegister); 16224514f5e3Sopenharmony_ci if (type == FrameTransitionType::OTHER_TO_BASELINE_CHECK || 16234514f5e3Sopenharmony_ci type == FrameTransitionType::BASELINE_TO_BASELINE_CHECK) { 16244514f5e3Sopenharmony_ci // check baselinecode, temp modify TOOD: need to check 16254514f5e3Sopenharmony_ci Label baselineCodeUndefined; 16264514f5e3Sopenharmony_ci __ Ldr(tempRegister, MemoryOperand(callTargetRegister, JSFunction::BASELINECODE_OFFSET)); 16274514f5e3Sopenharmony_ci __ Cmp(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED)); 16284514f5e3Sopenharmony_ci __ B(Condition::EQ, &baselineCodeUndefined); 16294514f5e3Sopenharmony_ci 16304514f5e3Sopenharmony_ci // check is compiling 16314514f5e3Sopenharmony_ci __ Cmp(tempRegister, Immediate(JSTaggedValue::VALUE_HOLE)); 16324514f5e3Sopenharmony_ci __ B(Condition::EQ, &baselineCodeUndefined); 16334514f5e3Sopenharmony_ci 16344514f5e3Sopenharmony_ci __ Ldr(tempRegister, MemoryOperand(tempRegister, MachineCode::FUNCADDR_OFFSET)); 16354514f5e3Sopenharmony_ci if (glue != X19) { 16364514f5e3Sopenharmony_ci __ Mov(X19, glue); 16374514f5e3Sopenharmony_ci } 16384514f5e3Sopenharmony_ci if (methodRegister != X21) { 16394514f5e3Sopenharmony_ci __ Mov(X21, methodRegister); 16404514f5e3Sopenharmony_ci } 16414514f5e3Sopenharmony_ci __ Mov(currentSlotRegister, Immediate(BASELINEJIT_PC_FLAG)); 16424514f5e3Sopenharmony_ci // -3: frame type, prevSp, pc 16434514f5e3Sopenharmony_ci __ Stur(currentSlotRegister, MemoryOperand(newSpRegister, -3 * FRAME_SLOT_SIZE)); 16444514f5e3Sopenharmony_ci __ Mov(Register(X29), newSpRegister); 16454514f5e3Sopenharmony_ci __ Br(tempRegister); 16464514f5e3Sopenharmony_ci __ Bind(&baselineCodeUndefined); 16474514f5e3Sopenharmony_ci } 16484514f5e3Sopenharmony_ci DispatchCall(assembler, pcRegister, newSpRegister); 16494514f5e3Sopenharmony_ci } 16504514f5e3Sopenharmony_ci} 16514514f5e3Sopenharmony_ci 16524514f5e3Sopenharmony_ci// Input: X19 - glue 16534514f5e3Sopenharmony_ci// FP - sp 16544514f5e3Sopenharmony_ci// X20 - callTarget 16554514f5e3Sopenharmony_ci// X21 - method 16564514f5e3Sopenharmony_civoid AsmInterpreterCall::DispatchCall(ExtendedAssembler *assembler, Register pcRegister, 16574514f5e3Sopenharmony_ci Register newSpRegister, Register accRegister) 16584514f5e3Sopenharmony_ci{ 16594514f5e3Sopenharmony_ci Register glueRegister = __ GlueRegister(); 16604514f5e3Sopenharmony_ci Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); 16614514f5e3Sopenharmony_ci Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD); 16624514f5e3Sopenharmony_ci 16634514f5e3Sopenharmony_ci if (glueRegister.GetId() != X19) { 16644514f5e3Sopenharmony_ci __ Mov(Register(X19), glueRegister); 16654514f5e3Sopenharmony_ci } 16664514f5e3Sopenharmony_ci __ Ldrh(Register(X24, W), MemoryOperand(methodRegister, Method::LITERAL_INFO_OFFSET)); 16674514f5e3Sopenharmony_ci if (accRegister == INVALID_REG) { 16684514f5e3Sopenharmony_ci __ Mov(Register(X23), Immediate(JSTaggedValue::VALUE_HOLE)); 16694514f5e3Sopenharmony_ci } else { 16704514f5e3Sopenharmony_ci ASSERT(accRegister == Register(X23)); 16714514f5e3Sopenharmony_ci } 16724514f5e3Sopenharmony_ci __ Ldr(Register(X22), MemoryOperand(callTargetRegister, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET)); 16734514f5e3Sopenharmony_ci __ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET)); 16744514f5e3Sopenharmony_ci __ Ldr(Register(X21), MemoryOperand(methodRegister, Method::CONSTANT_POOL_OFFSET)); 16754514f5e3Sopenharmony_ci __ Mov(Register(X20), pcRegister); 16764514f5e3Sopenharmony_ci __ Mov(Register(FP), newSpRegister); 16774514f5e3Sopenharmony_ci 16784514f5e3Sopenharmony_ci Register bcIndexRegister = __ AvailableRegister1(); 16794514f5e3Sopenharmony_ci Register tempRegister = __ AvailableRegister2(); 16804514f5e3Sopenharmony_ci __ Ldrb(bcIndexRegister.W(), MemoryOperand(pcRegister, 0)); 16814514f5e3Sopenharmony_ci __ Add(tempRegister, glueRegister, Operand(bcIndexRegister.W(), UXTW, FRAME_SLOT_SIZE_LOG2)); 16824514f5e3Sopenharmony_ci __ Ldr(tempRegister, MemoryOperand(tempRegister, JSThread::GlueData::GetBCStubEntriesOffset(false))); 16834514f5e3Sopenharmony_ci __ Br(tempRegister); 16844514f5e3Sopenharmony_ci} 16854514f5e3Sopenharmony_ci 16864514f5e3Sopenharmony_civoid AsmInterpreterCall::PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, 16874514f5e3Sopenharmony_ci Register currentSlot, Register callTarget, Register thisObj, Register method, Register pc, Register op) 16884514f5e3Sopenharmony_ci{ 16894514f5e3Sopenharmony_ci __ Mov(op, Immediate(static_cast<int32_t>(FrameType::ASM_INTERPRETER_FRAME))); 16904514f5e3Sopenharmony_ci __ Stp(prevSp, op, MemoryOperand(currentSlot, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // -2: frame type & prevSp 16914514f5e3Sopenharmony_ci __ Ldr(pc, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)); 16924514f5e3Sopenharmony_ci __ Stp(fp, pc, MemoryOperand(currentSlot, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // -2: pc & fp 16934514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(callTarget, JSFunction::LEXICAL_ENV_OFFSET)); 16944514f5e3Sopenharmony_ci __ Stp(op, Register(Zero), MemoryOperand(currentSlot, 16954514f5e3Sopenharmony_ci -2 * FRAME_SLOT_SIZE, // -2: jumpSizeAfterCall & env 16964514f5e3Sopenharmony_ci AddrMode::PREINDEX)); 16974514f5e3Sopenharmony_ci __ Mov(op, Immediate(JSTaggedValue::VALUE_HOLE)); 16984514f5e3Sopenharmony_ci __ Stp(thisObj, op, MemoryOperand(currentSlot, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // -2: acc & this 16994514f5e3Sopenharmony_ci __ Str(callTarget, MemoryOperand(currentSlot, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // -1: callTarget 17004514f5e3Sopenharmony_ci} 17014514f5e3Sopenharmony_ci 17024514f5e3Sopenharmony_civoid AsmInterpreterCall::GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs) 17034514f5e3Sopenharmony_ci{ 17044514f5e3Sopenharmony_ci __ Mov(numVregs, callField); 17054514f5e3Sopenharmony_ci __ Lsr(numVregs, numVregs, MethodLiteral::NumVregsBits::START_BIT); 17064514f5e3Sopenharmony_ci __ And(numVregs.W(), numVregs.W(), LogicalImmediate::Create( 17074514f5e3Sopenharmony_ci MethodLiteral::NumVregsBits::Mask() >> MethodLiteral::NumVregsBits::START_BIT, RegWSize)); 17084514f5e3Sopenharmony_ci} 17094514f5e3Sopenharmony_ci 17104514f5e3Sopenharmony_civoid AsmInterpreterCall::GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField, 17114514f5e3Sopenharmony_ci Register declaredNumArgs) 17124514f5e3Sopenharmony_ci{ 17134514f5e3Sopenharmony_ci __ Mov(declaredNumArgs, callField); 17144514f5e3Sopenharmony_ci __ Lsr(declaredNumArgs, declaredNumArgs, MethodLiteral::NumArgsBits::START_BIT); 17154514f5e3Sopenharmony_ci __ And(declaredNumArgs.W(), declaredNumArgs.W(), LogicalImmediate::Create( 17164514f5e3Sopenharmony_ci MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegWSize)); 17174514f5e3Sopenharmony_ci} 17184514f5e3Sopenharmony_ci 17194514f5e3Sopenharmony_civoid AsmInterpreterCall::PushAsmInterpEntryFrame(ExtendedAssembler *assembler) 17204514f5e3Sopenharmony_ci{ 17214514f5e3Sopenharmony_ci Register glue = __ GlueRegister(); 17224514f5e3Sopenharmony_ci Register fp(X29); 17234514f5e3Sopenharmony_ci Register sp(SP); 17244514f5e3Sopenharmony_ci 17254514f5e3Sopenharmony_ci size_t begin = __ GetCurrentPosition(); 17264514f5e3Sopenharmony_ci if (!assembler->FromInterpreterHandler()) { 17274514f5e3Sopenharmony_ci __ CalleeSave(); 17284514f5e3Sopenharmony_ci } 17294514f5e3Sopenharmony_ci 17304514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 17314514f5e3Sopenharmony_ci Register prevFrameRegister = __ TempRegister1(); 17324514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister2Scope scope2(assembler); 17334514f5e3Sopenharmony_ci Register frameTypeRegister = __ TempRegister2(); 17344514f5e3Sopenharmony_ci 17354514f5e3Sopenharmony_ci __ PushFpAndLr(); 17364514f5e3Sopenharmony_ci 17374514f5e3Sopenharmony_ci // prev managed fp is leave frame or nullptr(the first frame) 17384514f5e3Sopenharmony_ci __ Ldr(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); 17394514f5e3Sopenharmony_ci __ Mov(frameTypeRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME))); 17404514f5e3Sopenharmony_ci // 2 : prevSp & frame type 17414514f5e3Sopenharmony_ci __ Stp(prevFrameRegister, frameTypeRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 17424514f5e3Sopenharmony_ci // 2 : pc & glue 17434514f5e3Sopenharmony_ci __ Stp(glue, Register(Zero), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // pc 17444514f5e3Sopenharmony_ci if (!assembler->FromInterpreterHandler()) { 17454514f5e3Sopenharmony_ci size_t end = __ GetCurrentPosition(); 17464514f5e3Sopenharmony_ci if ((end - begin) != FrameCompletionPos::ARM64CppToAsmInterp) { 17474514f5e3Sopenharmony_ci LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64CppToAsmInterp 17484514f5e3Sopenharmony_ci << "This frame has been modified, and the offset CppToAsmInterp should be updated too."; 17494514f5e3Sopenharmony_ci } 17504514f5e3Sopenharmony_ci } 17514514f5e3Sopenharmony_ci __ Add(fp, sp, Immediate(4 * FRAME_SLOT_SIZE)); // 4: 32 means skip frame type, prevSp, pc and glue 17524514f5e3Sopenharmony_ci} 17534514f5e3Sopenharmony_ci 17544514f5e3Sopenharmony_civoid AsmInterpreterCall::PopAsmInterpEntryFrame(ExtendedAssembler *assembler) 17554514f5e3Sopenharmony_ci{ 17564514f5e3Sopenharmony_ci Register sp(SP); 17574514f5e3Sopenharmony_ci 17584514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister1Scope scope1(assembler); 17594514f5e3Sopenharmony_ci Register prevFrameRegister = __ TempRegister1(); 17604514f5e3Sopenharmony_ci [[maybe_unused]] TempRegister2Scope scope2(assembler); 17614514f5e3Sopenharmony_ci Register glue = __ TempRegister2(); 17624514f5e3Sopenharmony_ci // 2: glue & pc 17634514f5e3Sopenharmony_ci __ Ldp(glue, Register(Zero), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); 17644514f5e3Sopenharmony_ci // 2: skip frame type & prev 17654514f5e3Sopenharmony_ci __ Ldp(prevFrameRegister, Register(Zero), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); 17664514f5e3Sopenharmony_ci __ Str(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); 17674514f5e3Sopenharmony_ci size_t begin = __ GetCurrentPosition(); 17684514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 17694514f5e3Sopenharmony_ci if (!assembler->FromInterpreterHandler()) { 17704514f5e3Sopenharmony_ci __ CalleeRestore(); 17714514f5e3Sopenharmony_ci size_t end = __ GetCurrentPosition(); 17724514f5e3Sopenharmony_ci if ((end - begin) != FrameCompletionPos::ARM64AsmInterpToCpp) { 17734514f5e3Sopenharmony_ci LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64AsmInterpToCpp 17744514f5e3Sopenharmony_ci << "This frame has been modified, and the offset AsmInterpToCpp should be updated too."; 17754514f5e3Sopenharmony_ci } 17764514f5e3Sopenharmony_ci } 17774514f5e3Sopenharmony_ci} 17784514f5e3Sopenharmony_ci 17794514f5e3Sopenharmony_civoid AsmInterpreterCall::PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, 17804514f5e3Sopenharmony_ci Register &fpRegister, Register ¤tSlotRegister, Register &callTargetRegister, Register &thisRegister, 17814514f5e3Sopenharmony_ci Register &methodRegister, Register &contextRegister, Register &pcRegister, Register &operatorRegister) 17824514f5e3Sopenharmony_ci{ 17834514f5e3Sopenharmony_ci __ Mov(operatorRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_FRAME))); 17844514f5e3Sopenharmony_ci __ Stp(prevSpRegister, operatorRegister, 17854514f5e3Sopenharmony_ci MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // 2 : frameType and prevSp 17864514f5e3Sopenharmony_ci __ Ldr(pcRegister, MemoryOperand(methodRegister, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)); 17874514f5e3Sopenharmony_ci // offset need 8 align, GENERATOR_NREGS_OFFSET instead of GENERATOR_BC_OFFSET_OFFSET 17884514f5e3Sopenharmony_ci __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET)); 17894514f5e3Sopenharmony_ci // 32: get high 32bit 17904514f5e3Sopenharmony_ci __ Lsr(operatorRegister, operatorRegister, 32); 17914514f5e3Sopenharmony_ci __ Add(pcRegister, operatorRegister, pcRegister); 17924514f5e3Sopenharmony_ci // 2 : pc and fp 17934514f5e3Sopenharmony_ci __ Stp(fpRegister, pcRegister, MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 17944514f5e3Sopenharmony_ci // jumpSizeAfterCall 17954514f5e3Sopenharmony_ci __ Str(Register(Zero), MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 17964514f5e3Sopenharmony_ci __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_LEXICALENV_OFFSET)); 17974514f5e3Sopenharmony_ci // env 17984514f5e3Sopenharmony_ci __ Str(operatorRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 17994514f5e3Sopenharmony_ci __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_ACC_OFFSET)); 18004514f5e3Sopenharmony_ci // acc 18014514f5e3Sopenharmony_ci __ Str(operatorRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 18024514f5e3Sopenharmony_ci __ Stp(callTargetRegister, thisRegister, 18034514f5e3Sopenharmony_ci MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // 2 : acc and callTarget 18044514f5e3Sopenharmony_ci} 18054514f5e3Sopenharmony_ci 18064514f5e3Sopenharmony_civoid AsmInterpreterCall::CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, 18074514f5e3Sopenharmony_ci Register &callTarget, Register &method, Register &pc, Register &temp) 18084514f5e3Sopenharmony_ci{ 18094514f5e3Sopenharmony_ci // prepare call entry 18104514f5e3Sopenharmony_ci __ Mov(Register(X19), glue); // X19 - glue 18114514f5e3Sopenharmony_ci __ Mov(Register(FP), newSp); // FP - sp 18124514f5e3Sopenharmony_ci __ Mov(Register(X20), pc); // X20 - pc 18134514f5e3Sopenharmony_ci __ Ldr(Register(X21), MemoryOperand(method, Method::CONSTANT_POOL_OFFSET)); // X21 - constantpool 18144514f5e3Sopenharmony_ci __ Ldr(Register(X22), MemoryOperand(callTarget, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET)); 18154514f5e3Sopenharmony_ci __ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET)); // X22 - profileTypeInfo 18164514f5e3Sopenharmony_ci __ Mov(Register(X23), Immediate(JSTaggedValue::Hole().GetRawData())); // X23 - acc 18174514f5e3Sopenharmony_ci __ Ldr(Register(X24), MemoryOperand(method, Method::LITERAL_INFO_OFFSET)); // X24 - hotnessCounter 18184514f5e3Sopenharmony_ci 18194514f5e3Sopenharmony_ci // call the first bytecode handler 18204514f5e3Sopenharmony_ci __ Ldrb(temp.W(), MemoryOperand(pc, 0)); 18214514f5e3Sopenharmony_ci // 3 : 3 means *8 18224514f5e3Sopenharmony_ci __ Add(temp, glue, Operand(temp.W(), UXTW, FRAME_SLOT_SIZE_LOG2)); 18234514f5e3Sopenharmony_ci __ Ldr(temp, MemoryOperand(temp, JSThread::GlueData::GetBCStubEntriesOffset(false))); 18244514f5e3Sopenharmony_ci __ Br(temp); 18254514f5e3Sopenharmony_ci} 18264514f5e3Sopenharmony_ci 18274514f5e3Sopenharmony_civoid AsmInterpreterCall::CallNativeEntry(ExtendedAssembler *assembler) 18284514f5e3Sopenharmony_ci{ 18294514f5e3Sopenharmony_ci Label callFastBuiltin; 18304514f5e3Sopenharmony_ci Label callNativeBuiltin; 18314514f5e3Sopenharmony_ci Register glue(X0); 18324514f5e3Sopenharmony_ci Register argv(X5); 18334514f5e3Sopenharmony_ci Register method(X2); 18344514f5e3Sopenharmony_ci Register function(X1); 18354514f5e3Sopenharmony_ci Register nativeCode(X7); 18364514f5e3Sopenharmony_ci Register temp(X9); 18374514f5e3Sopenharmony_ci Register callFieldRegister(X3); 18384514f5e3Sopenharmony_ci // get native pointer 18394514f5e3Sopenharmony_ci __ Ldr(nativeCode, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)); 18404514f5e3Sopenharmony_ci __ Tbnz(callFieldRegister, MethodLiteral::IsFastBuiltinBit::START_BIT, &callFastBuiltin); 18414514f5e3Sopenharmony_ci 18424514f5e3Sopenharmony_ci __ Bind(&callNativeBuiltin); 18434514f5e3Sopenharmony_ci Register sp(SP); 18444514f5e3Sopenharmony_ci // 2: function & align 18454514f5e3Sopenharmony_ci __ Stp(function, Register(Zero), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); 18464514f5e3Sopenharmony_ci // 2: skip argc & thread 18474514f5e3Sopenharmony_ci __ Sub(sp, sp, Immediate(2 * FRAME_SLOT_SIZE)); 18484514f5e3Sopenharmony_ci PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_ENTRY_FRAME, temp, argv); 18494514f5e3Sopenharmony_ci __ Mov(temp, argv); 18504514f5e3Sopenharmony_ci __ Sub(Register(X0), temp, Immediate(2 * FRAME_SLOT_SIZE)); // 2: skip argc & thread 18514514f5e3Sopenharmony_ci CallNativeInternal(assembler, nativeCode); 18524514f5e3Sopenharmony_ci 18534514f5e3Sopenharmony_ci // 4: skip function 18544514f5e3Sopenharmony_ci __ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE)); 18554514f5e3Sopenharmony_ci __ Ret(); 18564514f5e3Sopenharmony_ci 18574514f5e3Sopenharmony_ci __ Bind(&callFastBuiltin); 18584514f5e3Sopenharmony_ci CallFastBuiltin(assembler, &callNativeBuiltin); 18594514f5e3Sopenharmony_ci} 18604514f5e3Sopenharmony_ci 18614514f5e3Sopenharmony_civoid AsmInterpreterCall::CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin) 18624514f5e3Sopenharmony_ci{ 18634514f5e3Sopenharmony_ci Label lCall1; 18644514f5e3Sopenharmony_ci Label lCall2; 18654514f5e3Sopenharmony_ci Label lCall3; 18664514f5e3Sopenharmony_ci Label callEntry; 18674514f5e3Sopenharmony_ci Register sp(SP); 18684514f5e3Sopenharmony_ci Register glue(X0); 18694514f5e3Sopenharmony_ci Register function(X1); 18704514f5e3Sopenharmony_ci Register method(X2); 18714514f5e3Sopenharmony_ci Register argc(X4); 18724514f5e3Sopenharmony_ci Register argv(X5); 18734514f5e3Sopenharmony_ci Register nativeCode(X7); 18744514f5e3Sopenharmony_ci 18754514f5e3Sopenharmony_ci Register builtinId = __ AvailableRegister1(); 18764514f5e3Sopenharmony_ci Register temp = __ AvailableRegister2(); 18774514f5e3Sopenharmony_ci // get builtinid 18784514f5e3Sopenharmony_ci __ Ldr(builtinId, MemoryOperand(method, Method::EXTRA_LITERAL_INFO_OFFSET)); // get extra literal 18794514f5e3Sopenharmony_ci __ And(builtinId.W(), builtinId.W(), LogicalImmediate::Create(0xff, RegWSize)); 18804514f5e3Sopenharmony_ci __ Cmp(builtinId.W(), Immediate(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST)); 18814514f5e3Sopenharmony_ci __ B(Condition::GE, callNativeBuiltin); 18824514f5e3Sopenharmony_ci 18834514f5e3Sopenharmony_ci __ Cmp(argc, Immediate(3)); // 3: number of args 18844514f5e3Sopenharmony_ci __ B(Condition::HI, callNativeBuiltin); 18854514f5e3Sopenharmony_ci 18864514f5e3Sopenharmony_ci // get builtin func addr 18874514f5e3Sopenharmony_ci __ Add(builtinId, glue, Operand(builtinId.W(), UXTW, FRAME_SLOT_SIZE_LOG2)); 18884514f5e3Sopenharmony_ci __ Ldr(builtinId, MemoryOperand(builtinId, JSThread::GlueData::GetBuiltinsStubEntriesOffset(false))); 18894514f5e3Sopenharmony_ci // create frame 18904514f5e3Sopenharmony_ci PushAsmBridgeFrame(assembler); 18914514f5e3Sopenharmony_ci __ Mov(temp, function); 18924514f5e3Sopenharmony_ci __ Mov(X1, nativeCode); 18934514f5e3Sopenharmony_ci __ Mov(X2, temp); 18944514f5e3Sopenharmony_ci __ Mov(temp, argv); 18954514f5e3Sopenharmony_ci __ Mov(X5, argc); 18964514f5e3Sopenharmony_ci __ Ldr(X3, MemoryOperand(temp, FRAME_SLOT_SIZE)); 18974514f5e3Sopenharmony_ci __ Ldr(X4, MemoryOperand(temp, DOUBLE_SLOT_SIZE)); 18984514f5e3Sopenharmony_ci 18994514f5e3Sopenharmony_ci __ Cmp(Register(X5), Immediate(0)); 19004514f5e3Sopenharmony_ci __ B(Condition::NE, &lCall1); 19014514f5e3Sopenharmony_ci __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 19024514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 19034514f5e3Sopenharmony_ci __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX)); 19044514f5e3Sopenharmony_ci __ B(&callEntry); 19054514f5e3Sopenharmony_ci 19064514f5e3Sopenharmony_ci __ Bind(&lCall1); 19074514f5e3Sopenharmony_ci { 19084514f5e3Sopenharmony_ci __ Cmp(Register(X5), Immediate(1)); 19094514f5e3Sopenharmony_ci __ B(Condition::NE, &lCall2); 19104514f5e3Sopenharmony_ci __ Ldr(Register(X6), MemoryOperand(temp, TRIPLE_SLOT_SIZE)); 19114514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); // reset x7 19124514f5e3Sopenharmony_ci __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX)); 19134514f5e3Sopenharmony_ci __ B(&callEntry); 19144514f5e3Sopenharmony_ci } 19154514f5e3Sopenharmony_ci 19164514f5e3Sopenharmony_ci __ Bind(&lCall2); 19174514f5e3Sopenharmony_ci { 19184514f5e3Sopenharmony_ci __ Cmp(Register(X5), Immediate(2)); // 2: number of args 19194514f5e3Sopenharmony_ci __ B(Condition::NE, &lCall3); 19204514f5e3Sopenharmony_ci __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED)); 19214514f5e3Sopenharmony_ci __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX)); 19224514f5e3Sopenharmony_ci __ Ldp(Register(X6), Register(X7), MemoryOperand(temp, TRIPLE_SLOT_SIZE)); 19234514f5e3Sopenharmony_ci __ B(&callEntry); 19244514f5e3Sopenharmony_ci } 19254514f5e3Sopenharmony_ci 19264514f5e3Sopenharmony_ci __ Bind(&lCall3); 19274514f5e3Sopenharmony_ci { 19284514f5e3Sopenharmony_ci __ Ldr(Register(X7), MemoryOperand(temp, QUINTUPLE_SLOT_SIZE)); 19294514f5e3Sopenharmony_ci __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX)); 19304514f5e3Sopenharmony_ci __ Ldp(Register(X6), Register(X7), MemoryOperand(temp, TRIPLE_SLOT_SIZE)); // get arg0 arg1 19314514f5e3Sopenharmony_ci __ B(&callEntry); 19324514f5e3Sopenharmony_ci } 19334514f5e3Sopenharmony_ci 19344514f5e3Sopenharmony_ci __ Bind(&callEntry); 19354514f5e3Sopenharmony_ci { 19364514f5e3Sopenharmony_ci __ Blr(builtinId); 19374514f5e3Sopenharmony_ci __ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE)); 19384514f5e3Sopenharmony_ci } 19394514f5e3Sopenharmony_ci PopAsmBridgeFrame(assembler); 19404514f5e3Sopenharmony_ci __ Ret(); 19414514f5e3Sopenharmony_ci} 19424514f5e3Sopenharmony_ci 19434514f5e3Sopenharmony_civoid AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, 19444514f5e3Sopenharmony_ci Register fp, Register op) 19454514f5e3Sopenharmony_ci{ 19464514f5e3Sopenharmony_ci if (fp != Register(SP)) { 19474514f5e3Sopenharmony_ci __ Mov(Register(SP), fp); 19484514f5e3Sopenharmony_ci } 19494514f5e3Sopenharmony_ci __ Mov(op, Immediate(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException)); 19504514f5e3Sopenharmony_ci // 3 : 3 means *8 19514514f5e3Sopenharmony_ci __ Add(op, glue, Operand(op, LSL, 3)); 19524514f5e3Sopenharmony_ci __ Ldr(op, MemoryOperand(op, JSThread::GlueData::GetRTStubEntriesOffset(false))); 19534514f5e3Sopenharmony_ci if (glue.GetId() != X0) { 19544514f5e3Sopenharmony_ci __ Mov(Register(X0), glue); 19554514f5e3Sopenharmony_ci } 19564514f5e3Sopenharmony_ci __ Blr(op); 19574514f5e3Sopenharmony_ci __ RestoreFpAndLr(); 19584514f5e3Sopenharmony_ci __ Ret(); 19594514f5e3Sopenharmony_ci} 19604514f5e3Sopenharmony_ci#undef __ 19614514f5e3Sopenharmony_ci} // panda::ecmascript::aarch64