1/* 2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/compiler/trampoline/x64/common_call.h" 17 18#include "ecmascript/compiler/assembler/assembler.h" 19#include "ecmascript/compiler/rt_call_signature.h" 20#include "ecmascript/ecma_runtime_call_info.h" 21#include "ecmascript/frames.h" 22#include "ecmascript/js_function.h" 23#include "ecmascript/method.h" 24#include "ecmascript/js_thread.h" 25#include "ecmascript/js_generator_object.h" 26#include "ecmascript/message_string.h" 27#include "ecmascript/runtime_call_id.h" 28 29namespace panda::ecmascript::x64 { 30#define __ assembler-> 31 32void CommonCall::CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV) 33{ 34 Label loopBeginning; 35 Register arg = __ AvailableRegister1(); 36 __ Bind(&loopBeginning); 37 __ Movq(Operand(argV, argc, Scale::Times8, -FRAME_SLOT_SIZE), arg); // -8: stack index 38 __ Pushq(arg); 39 __ Subq(1, argc); 40 __ Ja(&loopBeginning); 41} 42 43void CommonCall::PushAsmInterpBridgeFrame(ExtendedAssembler *assembler) 44{ 45 // construct asm interpreter bridge frame 46 __ Pushq(static_cast<int64_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME)); 47 __ Pushq(rbp); 48 __ Pushq(0); // pc 49 __ Leaq(Operand(rsp, 24), rbp); // 24: skip pc, prevSp and frame type 50 __ PushAlignBytes(); 51 if (!assembler->FromInterpreterHandler()) { 52 __ PushCppCalleeSaveRegisters(); 53 } 54} 55 56void CommonCall::GetArgvAtStack(ExtendedAssembler *assembler) 57{ 58 Register r13 = __ CppJSCallAvailableRegister1(); 59 Register r14 = __ CppJSCallAvailableRegister2(); 60 __ Movq(Operand(rbp, FRAME_SLOT_SIZE), r13); 61 __ Movq(Operand(rbp, 2 * FRAME_SLOT_SIZE), r14); // 2: skip second argv 62} 63 64void CommonCall::PopAsmInterpBridgeFrame(ExtendedAssembler *assembler) 65{ 66 if (!assembler->FromInterpreterHandler()) { 67 __ PopCppCalleeSaveRegisters(); 68 } 69 __ PopAlignBytes(); 70 __ Addq(8, rsp); // 8: skip pc 71 __ Popq(rbp); 72 __ Addq(8, rsp); // 8: skip frame type 73} 74 75void CommonCall::PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc) 76{ 77 Label loopBeginning; 78 __ Bind(&loopBeginning); 79 __ Pushq(JSTaggedValue::Undefined().GetRawData()); 80 __ Subq(1, argc); 81 __ Ja(&loopBeginning); 82} 83 84void CommonCall::PushArgsWithArgvAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc, 85 Register argv, Register op1, Register op2, Label *stackOverflow) 86{ 87 ASSERT(stackOverflow != nullptr); 88 StackOverflowCheck(assembler, glue, argc, op1, op2, stackOverflow); 89 Register opArgc = argc; 90 Register op = op1; 91 if (op1 != op2) { 92 // use op2 as opArgc and will not change argc register 93 opArgc = op2; 94 __ Movq(argc, opArgc); 95 } 96 Label loopBeginning; 97 __ Bind(&loopBeginning); 98 __ Movq(Operand(argv, opArgc, Times8, -8), op); // 8: 8 bytes argv crash rdx=0x8 99 __ Pushq(op); 100 __ Subq(1, opArgc); 101 __ Ja(&loopBeginning); 102} 103 104void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register numArgs, Register op1, 105 Register op2, Label *stackOverflow) 106{ 107 Register temp1 = op1; 108 Register temp2 = op2; 109 if (op1 == op2) { 110 // reuse glue as an op register for temporary 111 __ Pushq(glue); 112 temp2 = glue; 113 } 114 __ Movq(Operand(glue, JSThread::GlueData::GetStackLimitOffset(false)), temp1); 115 __ Movq(rsp, temp2); 116 __ Subq(temp1, temp2); 117 __ Movl(numArgs, temp1); 118 __ Shlq(3, temp1); // 3: each arg occupies 8 bytes 119 __ Cmpq(temp1, temp2); 120 if (op1 == op2) { 121 __ Popq(glue); 122 } 123 __ Jle(stackOverflow); 124} 125 126void CommonCall::PushAsmBridgeFrame(ExtendedAssembler *assembler) 127{ 128 __ Pushq(rbp); 129 __ Pushq(static_cast<int32_t>(FrameType::ASM_BRIDGE_FRAME)); 130 __ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); 131} 132 133void CommonCall::PopAsmBridgeFrame(ExtendedAssembler *assembler) 134{ 135 __ Addq(FRAME_SLOT_SIZE, rsp); // skip type 136 __ Popq(rbp); 137} 138#undef __ 139} // namespace panda::ecmascript::x64 140