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