1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CODEGEN_X64_INTERFACE_DESCRIPTORS_X64_INL_H_
6 #define V8_CODEGEN_X64_INTERFACE_DESCRIPTORS_X64_INL_H_
7
8 #if V8_TARGET_ARCH_X64
9
10 #include "src/codegen/interface-descriptors.h"
11
12 namespace v8 {
13 namespace internal {
14
DefaultRegisterArray()15 constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
16 auto registers = RegisterArray(rax, rbx, rcx, rdx, rdi);
17 STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
18 return registers;
19 }
20
21 #if DEBUG
22 template <typename DerivedDescriptor>
23 void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData * data,int nof_expected_args)24 VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data,
25 int nof_expected_args) {
26 RegList allocatable_regs = data->allocatable_registers();
27 if (nof_expected_args >= 1) DCHECK(allocatable_regs.has(arg_reg_1));
28 if (nof_expected_args >= 2) DCHECK(allocatable_regs.has(arg_reg_2));
29 if (nof_expected_args >= 3) DCHECK(allocatable_regs.has(arg_reg_3));
30 if (nof_expected_args >= 4) DCHECK(allocatable_regs.has(arg_reg_4));
31 // Additional arguments are passed on the stack.
32 }
33 #endif // DEBUG
34
35 // static
registers()36 constexpr auto WriteBarrierDescriptor::registers() {
37 #if V8_TARGET_OS_WIN
38 return RegisterArray(rdi, r8, rcx, rax, r9, rdx, rsi);
39 #else
40 return RegisterArray(rdi, rbx, rdx, rcx, rax, rsi);
41 #endif // V8_TARGET_OS_WIN
42 }
43
44 #ifdef V8_IS_TSAN
45 // static
registers()46 constexpr auto TSANStoreDescriptor::registers() {
47 return RegisterArray(arg_reg_1, arg_reg_2, kReturnRegister0);
48 }
49
50 // static
registers()51 constexpr auto TSANLoadDescriptor::registers() {
52 return RegisterArray(arg_reg_1, kReturnRegister0);
53 }
54 #endif // V8_IS_TSAN
55
56 // static
ReceiverRegister()57 constexpr Register LoadDescriptor::ReceiverRegister() { return rdx; }
58 // static
NameRegister()59 constexpr Register LoadDescriptor::NameRegister() { return rcx; }
60 // static
SlotRegister()61 constexpr Register LoadDescriptor::SlotRegister() { return rax; }
62
63 // static
VectorRegister()64 constexpr Register LoadWithVectorDescriptor::VectorRegister() { return rbx; }
65
66 // static
ReceiverRegister()67 constexpr Register KeyedLoadBaselineDescriptor::ReceiverRegister() {
68 return rdx;
69 }
70 // static
NameRegister()71 constexpr Register KeyedLoadBaselineDescriptor::NameRegister() {
72 return kInterpreterAccumulatorRegister;
73 }
74 // static
SlotRegister()75 constexpr Register KeyedLoadBaselineDescriptor::SlotRegister() { return rcx; }
76
77 // static
VectorRegister()78 constexpr Register KeyedLoadWithVectorDescriptor::VectorRegister() {
79 return rbx;
80 }
81
82 // static
ReceiverRegister()83 constexpr Register KeyedHasICBaselineDescriptor::ReceiverRegister() {
84 return kInterpreterAccumulatorRegister;
85 }
86 // static
NameRegister()87 constexpr Register KeyedHasICBaselineDescriptor::NameRegister() { return rdx; }
88 // static
SlotRegister()89 constexpr Register KeyedHasICBaselineDescriptor::SlotRegister() { return rcx; }
90
91 // static
VectorRegister()92 constexpr Register KeyedHasICWithVectorDescriptor::VectorRegister() {
93 return rbx;
94 }
95
96 // static
97 constexpr Register
LookupStartObjectRegister()98 LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
99 return rdi;
100 }
101
102 // static
ReceiverRegister()103 constexpr Register StoreDescriptor::ReceiverRegister() { return rdx; }
104 // static
NameRegister()105 constexpr Register StoreDescriptor::NameRegister() { return rcx; }
106 // static
ValueRegister()107 constexpr Register StoreDescriptor::ValueRegister() { return rax; }
108 // static
SlotRegister()109 constexpr Register StoreDescriptor::SlotRegister() { return rdi; }
110
111 // static
VectorRegister()112 constexpr Register StoreWithVectorDescriptor::VectorRegister() { return rbx; }
113
114 // static
MapRegister()115 constexpr Register StoreTransitionDescriptor::MapRegister() { return r11; }
116
117 // static
HolderRegister()118 constexpr Register ApiGetterDescriptor::HolderRegister() { return rcx; }
119 // static
CallbackRegister()120 constexpr Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
121
122 // static
ObjectRegister()123 constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
124 // static
KeyRegister()125 constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
126
127 // static
ParamsSizeRegister()128 constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
129 return rbx;
130 }
131 // static
WeightRegister()132 constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() {
133 return rcx;
134 }
135
136 // static
ArgumentRegister()137 constexpr Register TypeConversionDescriptor::ArgumentRegister() { return rax; }
138
139 // static
registers()140 constexpr auto TypeofDescriptor::registers() { return RegisterArray(rax); }
141
142 // static
registers()143 constexpr auto CallTrampolineDescriptor::registers() {
144 // rax : number of arguments
145 // rdi : the target to call
146 return RegisterArray(rdi, rax);
147 }
148 // static
registers()149 constexpr auto CopyDataPropertiesWithExcludedPropertiesDescriptor::registers() {
150 // rdi : the source
151 // rax : the excluded property count
152 return RegisterArray(rdi, rax);
153 }
154
155 // static
156 constexpr auto
registers()157 CopyDataPropertiesWithExcludedPropertiesOnStackDescriptor::registers() {
158 // rdi : the source
159 // rax : the excluded property count
160 // rcx : the excluded property base
161 return RegisterArray(rdi, rax, rcx);
162 }
163
164 // static
registers()165 constexpr auto CallVarargsDescriptor::registers() {
166 // rax : number of arguments (on the stack)
167 // rdi : the target to call
168 // rcx : arguments list length (untagged)
169 // rbx : arguments list (FixedArray)
170 return RegisterArray(rdi, rax, rcx, rbx);
171 }
172
173 // static
registers()174 constexpr auto CallForwardVarargsDescriptor::registers() {
175 // rax : number of arguments
176 // rcx : start index (to support rest parameters)
177 // rdi : the target to call
178 return RegisterArray(rdi, rax, rcx);
179 }
180
181 // static
registers()182 constexpr auto CallFunctionTemplateDescriptor::registers() {
183 // rdx: the function template info
184 // rcx: number of arguments (on the stack)
185 return RegisterArray(rdx, rcx);
186 }
187
188 // static
registers()189 constexpr auto CallWithSpreadDescriptor::registers() {
190 // rax : number of arguments (on the stack)
191 // rdi : the target to call
192 // rbx : the object to spread
193 return RegisterArray(rdi, rax, rbx);
194 }
195
196 // static
registers()197 constexpr auto CallWithArrayLikeDescriptor::registers() {
198 // rdi : the target to call
199 // rbx : the arguments list
200 return RegisterArray(rdi, rbx);
201 }
202
203 // static
registers()204 constexpr auto ConstructVarargsDescriptor::registers() {
205 // rax : number of arguments (on the stack)
206 // rdi : the target to call
207 // rdx : the new target
208 // rcx : arguments list length (untagged)
209 // rbx : arguments list (FixedArray)
210 return RegisterArray(rdi, rdx, rax, rcx, rbx);
211 }
212
213 // static
registers()214 constexpr auto ConstructForwardVarargsDescriptor::registers() {
215 // rax : number of arguments
216 // rdx : the new target
217 // rcx : start index (to support rest parameters)
218 // rdi : the target to call
219 return RegisterArray(rdi, rdx, rax, rcx);
220 }
221
222 // static
registers()223 constexpr auto ConstructWithSpreadDescriptor::registers() {
224 // rax : number of arguments (on the stack)
225 // rdi : the target to call
226 // rdx : the new target
227 // rbx : the object to spread
228 return RegisterArray(rdi, rdx, rax, rbx);
229 }
230
231 // static
registers()232 constexpr auto ConstructWithArrayLikeDescriptor::registers() {
233 // rdi : the target to call
234 // rdx : the new target
235 // rbx : the arguments list
236 return RegisterArray(rdi, rdx, rbx);
237 }
238
239 // static
registers()240 constexpr auto ConstructStubDescriptor::registers() {
241 // rax : number of arguments
242 // rdx : the new target
243 // rdi : the target to call
244 // rbx : allocation site or undefined
245 return RegisterArray(rdi, rdx, rax, rbx);
246 }
247
248 // static
registers()249 constexpr auto AbortDescriptor::registers() { return RegisterArray(rdx); }
250
251 // static
registers()252 constexpr auto CompareDescriptor::registers() {
253 return RegisterArray(rdx, rax);
254 }
255
256 // static
registers()257 constexpr auto BinaryOpDescriptor::registers() {
258 return RegisterArray(rdx, rax);
259 }
260
261 // static
registers()262 constexpr auto Compare_BaselineDescriptor::registers() {
263 return RegisterArray(rdx, rax, rbx);
264 }
265
266 // static
registers()267 constexpr auto BinaryOp_BaselineDescriptor::registers() {
268 return RegisterArray(rdx, rax, rbx);
269 }
270
271 // static
registers()272 constexpr auto BinarySmiOp_BaselineDescriptor::registers() {
273 return RegisterArray(rax, rdx, rbx);
274 }
275
276 // static
registers()277 constexpr auto ApiCallbackDescriptor::registers() {
278 return RegisterArray(rdx, // api function address
279 rcx, // argument count (not including receiver)
280 rbx, // call data
281 rdi); // holder
282 }
283
284 // static
registers()285 constexpr auto InterpreterDispatchDescriptor::registers() {
286 return RegisterArray(
287 kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
288 kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
289 }
290
291 // static
registers()292 constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
293 return RegisterArray(rax, // argument count
294 rbx, // address of first argument
295 rdi); // the target callable to be call
296 }
297
298 // static
registers()299 constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
300 return RegisterArray(
301 rax, // argument count
302 rcx, // address of first argument
303 rdi, // constructor to call
304 rdx, // new target
305 rbx); // allocation site feedback if available, undefined otherwise
306 }
307
308 // static
registers()309 constexpr auto ResumeGeneratorDescriptor::registers() {
310 return RegisterArray(
311 rax, // the value to pass to the generator
312 rdx); // the JSGeneratorObject / JSAsyncGeneratorObject to resume
313 }
314
315 // static
registers()316 constexpr auto RunMicrotasksEntryDescriptor::registers() {
317 return RegisterArray(arg_reg_1, arg_reg_2);
318 }
319
320 } // namespace internal
321 } // namespace v8
322
323 #endif // V8_TARGET_ARCH_X64
324
325 #endif // V8_CODEGEN_X64_INTERFACE_DESCRIPTORS_X64_INL_H_
326