• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/aarch64/common_call.h"
17 
18 #include "ecmascript/compiler/assembler/assembler.h"
19 #include "ecmascript/compiler/argument_accessor.h"
20 #include "ecmascript/compiler/common_stubs.h"
21 #include "ecmascript/compiler/rt_call_signature.h"
22 #include "ecmascript/ecma_runtime_call_info.h"
23 #include "ecmascript/frames.h"
24 #include "ecmascript/js_function.h"
25 #include "ecmascript/js_thread.h"
26 #include "ecmascript/js_generator_object.h"
27 #include "ecmascript/message_string.h"
28 #include "ecmascript/method.h"
29 #include "ecmascript/runtime_call_id.h"
30 
31 namespace panda::ecmascript::aarch64 {
32 using Label = panda::ecmascript::Label;
33 #define __ assembler->
34 
PushAsmInterpBridgeFrame(ExtendedAssembler * assembler)35 void CommonCall::PushAsmInterpBridgeFrame(ExtendedAssembler *assembler)
36 {
37     Register fp(X29);
38     Register sp(SP);
39 
40     [[maybe_unused]] TempRegister1Scope scope1(assembler);
41     Register frameTypeRegister = __ TempRegister1();
42 
43     __ Mov(frameTypeRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME)));
44     // 2 : return addr & frame type
45     __ Stp(frameTypeRegister, Register(X30), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
46     // 2 : prevSp & pc
47     __ Stp(Register(Zero), Register(FP), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
48     __ Add(fp, sp, Immediate(24));  // 24: skip frame type, prevSp, pc
49 
50     if (!assembler->FromInterpreterHandler()) {
51         __ CalleeSave();
52     }
53 }
54 
PopAsmInterpBridgeFrame(ExtendedAssembler * assembler)55 void CommonCall::PopAsmInterpBridgeFrame(ExtendedAssembler *assembler)
56 {
57     Register sp(SP);
58 
59     if (!assembler->FromInterpreterHandler()) {
60         __ CalleeRestore();
61     }
62     // 2: prevSp & pc
63     __ Ldp(Register(Zero), Register(FP), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
64     // 2: return addr & frame type
65     __ Ldp(Register(Zero), Register(X30), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
66 }
67 
68 
PushLeaveFrame(ExtendedAssembler * assembler,Register glue)69 void CommonCall::PushLeaveFrame(ExtendedAssembler *assembler, Register glue)
70 {
71     TempRegister2Scope temp2Scope(assembler);
72     Register frameType = __ TempRegister2();
73     Register currentSp(X6);
74     Register sp(SP);
75 
76     // construct leave frame
77     __ Mov(frameType, Immediate(static_cast<int64_t>(FrameType::LEAVE_FRAME)));
78     __ PushFpAndLr();
79     // 2 : 2 means pairs
80     __ Stp(Register(X19), frameType, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
81     __ Add(Register(FP), sp, Immediate(DOUBLE_SLOT_SIZE));
82     // save to thread currentLeaveFrame_;
83     __ Str(Register(FP), MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
84 }
85 
86 
PopLeaveFrame(ExtendedAssembler * assembler)87 void CommonCall::PopLeaveFrame(ExtendedAssembler *assembler)
88 {
89     Register sp(SP);
90     Register currentSp(X6);
91     TempRegister2Scope temp2Scope(assembler);
92     Register frameType = __ TempRegister2();
93     // 2 : 2 means pairs
94     __ Ldp(Register(X19), frameType, MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
95     __ RestoreFpAndLr();
96 }
97 
PushArgsWithArgv(ExtendedAssembler * assembler,Register glue,Register argc,Register argv,Register op,Register currentSlot,Label * next,Label * stackOverflow)98 void CommonCall::PushArgsWithArgv(ExtendedAssembler *assembler, Register glue, Register argc,
99     Register argv, Register op, Register currentSlot, Label *next, Label *stackOverflow)
100 {
101     Label loopBeginning;
102     if (next != nullptr) {
103         __ Cmp(argc.W(), Immediate(0));
104         __ B(Condition::LS, next);
105     }
106     if (stackOverflow != nullptr) {
107         StackOverflowCheck(assembler, glue, currentSlot, argc, op, stackOverflow);
108     }
109     __ Add(argv, argv, Operand(argc.W(), UXTW, 3));  // 3: argc * 8
110     __ Bind(&loopBeginning);
111     __ Ldr(op, MemoryOperand(argv, -FRAME_SLOT_SIZE, PREINDEX));  // -8: 8 bytes
112     __ Str(op, MemoryOperand(currentSlot, -FRAME_SLOT_SIZE, PREINDEX));  // -8: 8 bytes
113     __ Sub(argc.W(), argc.W(), Immediate(1));
114     __ Cbnz(argc.W(), &loopBeginning);
115 }
116 
PushUndefinedWithArgc(ExtendedAssembler * assembler,Register glue,Register argc,Register temp,Register currentSlot,Label * next,Label * stackOverflow)117 void CommonCall::PushUndefinedWithArgc(ExtendedAssembler *assembler, Register glue, Register argc, Register temp,
118     Register currentSlot, Label *next, Label *stackOverflow)
119 {
120     if (next != nullptr) {
121         __ Cmp(argc.W(), Immediate(0));
122         __ B(Condition::LE, next);
123     }
124     if (stackOverflow != nullptr) {
125         StackOverflowCheck(assembler, glue, currentSlot, argc, temp, stackOverflow);
126     }
127     Label loopBeginning;
128     __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED));
129     __ Bind(&loopBeginning);
130     __ Str(temp, MemoryOperand(currentSlot, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
131     __ Sub(argc.W(), argc.W(), Immediate(1));
132     __ Cbnz(argc.W(), &loopBeginning);
133 }
134 
StackOverflowCheck(ExtendedAssembler * assembler,Register glue,Register currentSlot,Register numArgs,Register op,Label * stackOverflow)135 void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register currentSlot,
136     Register numArgs, Register op, Label *stackOverflow)
137 {
138     __ Ldr(op, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false)));
139     Label skipThrow;
140     __ Sub(op, currentSlot, Operand(op, UXTX, 0));
141     __ Cmp(op, Operand(numArgs, LSL, 3));  // 3: each args occupies 8 bytes
142     __ B(Condition::GT, &skipThrow);
143     __ Ldr(op, MemoryOperand(glue, JSThread::GlueData::GetAllowCrossThreadExecutionOffset(false)));
144     __ Cbz(op, stackOverflow);
145     __ Bind(&skipThrow);
146 }
147 #undef __
148 }  // panda::ecmascript::aarch64