1// Copyright 2012 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#if V8_TARGET_ARCH_X64
6
7#include "src/interface-descriptors.h"
8
9namespace v8 {
10namespace internal {
11
12const Register CallInterfaceDescriptor::ContextRegister() { return rsi; }
13
14void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
15    CallInterfaceDescriptorData* data, int register_parameter_count) {
16  const Register default_stub_registers[] = {rax, rbx, rcx, rdx, rdi};
17  CHECK_LE(static_cast<size_t>(register_parameter_count),
18           arraysize(default_stub_registers));
19  data->InitializePlatformSpecific(register_parameter_count,
20                                   default_stub_registers);
21}
22
23const Register LoadDescriptor::ReceiverRegister() { return rdx; }
24const Register LoadDescriptor::NameRegister() { return rcx; }
25const Register LoadDescriptor::SlotRegister() { return rax; }
26
27
28const Register LoadWithVectorDescriptor::VectorRegister() { return rbx; }
29
30
31const Register StoreDescriptor::ReceiverRegister() { return rdx; }
32const Register StoreDescriptor::NameRegister() { return rcx; }
33const Register StoreDescriptor::ValueRegister() { return rax; }
34
35
36const Register VectorStoreICTrampolineDescriptor::SlotRegister() { return rdi; }
37
38
39const Register VectorStoreICDescriptor::VectorRegister() { return rbx; }
40
41
42const Register VectorStoreTransitionDescriptor::SlotRegister() { return rdi; }
43const Register VectorStoreTransitionDescriptor::VectorRegister() { return rbx; }
44const Register VectorStoreTransitionDescriptor::MapRegister() { return r11; }
45
46
47const Register StoreTransitionDescriptor::MapRegister() { return rbx; }
48
49
50const Register StoreGlobalViaContextDescriptor::SlotRegister() { return rbx; }
51const Register StoreGlobalViaContextDescriptor::ValueRegister() { return rax; }
52
53
54const Register StringCompareDescriptor::LeftRegister() { return rdx; }
55const Register StringCompareDescriptor::RightRegister() { return rax; }
56
57const Register ApiGetterDescriptor::HolderRegister() { return rcx; }
58const Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
59
60const Register MathPowTaggedDescriptor::exponent() { return rdx; }
61
62
63const Register MathPowIntegerDescriptor::exponent() {
64  return MathPowTaggedDescriptor::exponent();
65}
66
67
68const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
69const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
70
71
72void FastNewClosureDescriptor::InitializePlatformSpecific(
73    CallInterfaceDescriptorData* data) {
74  Register registers[] = {rbx};
75  data->InitializePlatformSpecific(arraysize(registers), registers);
76}
77
78
79void FastNewContextDescriptor::InitializePlatformSpecific(
80    CallInterfaceDescriptorData* data) {
81  Register registers[] = {rdi};
82  data->InitializePlatformSpecific(arraysize(registers), registers);
83}
84
85void FastNewObjectDescriptor::InitializePlatformSpecific(
86    CallInterfaceDescriptorData* data) {
87  Register registers[] = {rdi, rdx};
88  data->InitializePlatformSpecific(arraysize(registers), registers);
89}
90
91void FastNewRestParameterDescriptor::InitializePlatformSpecific(
92    CallInterfaceDescriptorData* data) {
93  Register registers[] = {rdi};
94  data->InitializePlatformSpecific(arraysize(registers), registers);
95}
96
97void FastNewSloppyArgumentsDescriptor::InitializePlatformSpecific(
98    CallInterfaceDescriptorData* data) {
99  Register registers[] = {rdi};
100  data->InitializePlatformSpecific(arraysize(registers), registers);
101}
102
103void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
104    CallInterfaceDescriptorData* data) {
105  Register registers[] = {rdi};
106  data->InitializePlatformSpecific(arraysize(registers), registers);
107}
108
109
110void TypeofDescriptor::InitializePlatformSpecific(
111    CallInterfaceDescriptorData* data) {
112  Register registers[] = {rbx};
113  data->InitializePlatformSpecific(arraysize(registers), registers);
114}
115
116
117// static
118const Register TypeConversionDescriptor::ArgumentRegister() { return rax; }
119
120void FastCloneRegExpDescriptor::InitializePlatformSpecific(
121    CallInterfaceDescriptorData* data) {
122  Register registers[] = {rdi, rax, rcx, rdx};
123  data->InitializePlatformSpecific(arraysize(registers), registers);
124}
125
126
127void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
128    CallInterfaceDescriptorData* data) {
129  Register registers[] = {rax, rbx, rcx};
130  data->InitializePlatformSpecific(arraysize(registers), registers);
131}
132
133
134void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
135    CallInterfaceDescriptorData* data) {
136  Register registers[] = {rax, rbx, rcx, rdx};
137  data->InitializePlatformSpecific(arraysize(registers), registers);
138}
139
140
141void CreateAllocationSiteDescriptor::InitializePlatformSpecific(
142    CallInterfaceDescriptorData* data) {
143  Register registers[] = {rbx, rdx};
144  data->InitializePlatformSpecific(arraysize(registers), registers);
145}
146
147
148void CreateWeakCellDescriptor::InitializePlatformSpecific(
149    CallInterfaceDescriptorData* data) {
150  Register registers[] = {rbx, rdx, rdi};
151  data->InitializePlatformSpecific(arraysize(registers), registers);
152}
153
154
155void CallFunctionDescriptor::InitializePlatformSpecific(
156    CallInterfaceDescriptorData* data) {
157  Register registers[] = {rdi};
158  data->InitializePlatformSpecific(arraysize(registers), registers);
159}
160
161
162void CallFunctionWithFeedbackDescriptor::InitializePlatformSpecific(
163    CallInterfaceDescriptorData* data) {
164  Register registers[] = {rdi, rdx};
165  data->InitializePlatformSpecific(arraysize(registers), registers);
166}
167
168
169void CallFunctionWithFeedbackAndVectorDescriptor::InitializePlatformSpecific(
170    CallInterfaceDescriptorData* data) {
171  Register registers[] = {rdi, rdx, rbx};
172  data->InitializePlatformSpecific(arraysize(registers), registers);
173}
174
175
176void CallConstructDescriptor::InitializePlatformSpecific(
177    CallInterfaceDescriptorData* data) {
178  // rax : number of arguments
179  // rbx : feedback vector
180  // rdx : slot in feedback vector (Smi, for RecordCallTarget)
181  // rdi : constructor function
182  // TODO(turbofan): So far we don't gather type feedback and hence skip the
183  // slot parameter, but ArrayConstructStub needs the vector to be undefined.
184  Register registers[] = {rax, rdi, rbx};
185  data->InitializePlatformSpecific(arraysize(registers), registers);
186}
187
188
189void CallTrampolineDescriptor::InitializePlatformSpecific(
190    CallInterfaceDescriptorData* data) {
191  // rax : number of arguments
192  // rdi : the target to call
193  Register registers[] = {rdi, rax};
194  data->InitializePlatformSpecific(arraysize(registers), registers);
195}
196
197
198void ConstructStubDescriptor::InitializePlatformSpecific(
199    CallInterfaceDescriptorData* data) {
200  // rax : number of arguments
201  // rdx : the new target
202  // rdi : the target to call
203  // rbx : allocation site or undefined
204  Register registers[] = {rdi, rdx, rax, rbx};
205  data->InitializePlatformSpecific(arraysize(registers), registers);
206}
207
208
209void ConstructTrampolineDescriptor::InitializePlatformSpecific(
210    CallInterfaceDescriptorData* data) {
211  // rax : number of arguments
212  // rdx : the new target
213  // rdi : the target to call
214  Register registers[] = {rdi, rdx, rax};
215  data->InitializePlatformSpecific(arraysize(registers), registers);
216}
217
218
219void RegExpConstructResultDescriptor::InitializePlatformSpecific(
220    CallInterfaceDescriptorData* data) {
221  Register registers[] = {rcx, rbx, rax};
222  data->InitializePlatformSpecific(arraysize(registers), registers);
223}
224
225
226void TransitionElementsKindDescriptor::InitializePlatformSpecific(
227    CallInterfaceDescriptorData* data) {
228  Register registers[] = {rax, rbx};
229  data->InitializePlatformSpecific(arraysize(registers), registers);
230}
231
232
233void AllocateHeapNumberDescriptor::InitializePlatformSpecific(
234    CallInterfaceDescriptorData* data) {
235  data->InitializePlatformSpecific(0, nullptr, nullptr);
236}
237
238#define SIMD128_ALLOC_DESC(TYPE, Type, type, lane_count, lane_type) \
239  void Allocate##Type##Descriptor::InitializePlatformSpecific(      \
240      CallInterfaceDescriptorData* data) {                          \
241    data->InitializePlatformSpecific(0, nullptr, nullptr);          \
242  }
243SIMD128_TYPES(SIMD128_ALLOC_DESC)
244#undef SIMD128_ALLOC_DESC
245
246void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
247    CallInterfaceDescriptorData* data) {
248  // register state
249  // rax -- number of arguments
250  // rdi -- function
251  // rbx -- allocation site with elements kind
252  Register registers[] = {rdi, rbx, rax};
253  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
254}
255
256void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
257    CallInterfaceDescriptorData* data) {
258  // register state
259  // rax -- number of arguments
260  // rdi -- function
261  // rbx -- allocation site with elements kind
262  Register registers[] = {rdi, rbx, rax};
263  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
264}
265
266void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
267    CallInterfaceDescriptorData* data) {
268  // register state
269  // rax -- number of arguments
270  // rdi -- function
271  // rbx -- allocation site with elements kind
272  Register registers[] = {rdi, rbx, rax};
273  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
274}
275
276void VarArgFunctionDescriptor::InitializePlatformSpecific(
277    CallInterfaceDescriptorData* data) {
278  // stack param count needs (arg count)
279  Register registers[] = {rax};
280  data->InitializePlatformSpecific(arraysize(registers), registers);
281}
282
283void CompareDescriptor::InitializePlatformSpecific(
284    CallInterfaceDescriptorData* data) {
285  Register registers[] = {rdx, rax};
286  data->InitializePlatformSpecific(arraysize(registers), registers);
287}
288
289
290void BinaryOpDescriptor::InitializePlatformSpecific(
291    CallInterfaceDescriptorData* data) {
292  Register registers[] = {rdx, rax};
293  data->InitializePlatformSpecific(arraysize(registers), registers);
294}
295
296
297void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
298    CallInterfaceDescriptorData* data) {
299  Register registers[] = {rcx, rdx, rax};
300  data->InitializePlatformSpecific(arraysize(registers), registers);
301}
302
303void CountOpDescriptor::InitializePlatformSpecific(
304    CallInterfaceDescriptorData* data) {
305  Register registers[] = {rax};
306  data->InitializePlatformSpecific(arraysize(registers), registers);
307}
308
309void StringAddDescriptor::InitializePlatformSpecific(
310    CallInterfaceDescriptorData* data) {
311  Register registers[] = {rdx, rax};
312  data->InitializePlatformSpecific(arraysize(registers), registers);
313}
314
315
316void KeyedDescriptor::InitializePlatformSpecific(
317    CallInterfaceDescriptorData* data) {
318  Register registers[] = {
319      rcx,  // key
320  };
321  data->InitializePlatformSpecific(arraysize(registers), registers);
322}
323
324
325void NamedDescriptor::InitializePlatformSpecific(
326    CallInterfaceDescriptorData* data) {
327  Register registers[] = {
328      rcx,  // name
329  };
330  data->InitializePlatformSpecific(arraysize(registers), registers);
331}
332
333
334void CallHandlerDescriptor::InitializePlatformSpecific(
335    CallInterfaceDescriptorData* data) {
336  Register registers[] = {
337      rdx,  // receiver
338  };
339  data->InitializePlatformSpecific(arraysize(registers), registers);
340}
341
342
343void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
344    CallInterfaceDescriptorData* data) {
345  Register registers[] = {
346      rdi,  // JSFunction
347      rdx,  // the new target
348      rax,  // actual number of arguments
349      rbx,  // expected number of arguments
350  };
351  data->InitializePlatformSpecific(arraysize(registers), registers);
352}
353
354void ApiCallbackDescriptorBase::InitializePlatformSpecific(
355    CallInterfaceDescriptorData* data) {
356  Register registers[] = {
357      rdi,  // callee
358      rbx,  // call_data
359      rcx,  // holder
360      rdx,  // api_function_address
361  };
362  data->InitializePlatformSpecific(arraysize(registers), registers);
363}
364
365void InterpreterDispatchDescriptor::InitializePlatformSpecific(
366    CallInterfaceDescriptorData* data) {
367  Register registers[] = {
368      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
369      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
370  data->InitializePlatformSpecific(arraysize(registers), registers);
371}
372
373void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
374    CallInterfaceDescriptorData* data) {
375  Register registers[] = {
376      rax,  // argument count (not including receiver)
377      rbx,  // address of first argument
378      rdi   // the target callable to be call
379  };
380  data->InitializePlatformSpecific(arraysize(registers), registers);
381}
382
383void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
384    CallInterfaceDescriptorData* data) {
385  Register registers[] = {
386      rax,  // argument count (not including receiver)
387      rdx,  // new target
388      rdi,  // constructor
389      rbx,  // address of first argument
390  };
391  data->InitializePlatformSpecific(arraysize(registers), registers);
392}
393
394void InterpreterCEntryDescriptor::InitializePlatformSpecific(
395    CallInterfaceDescriptorData* data) {
396  Register registers[] = {
397      rax,  // argument count (argc)
398      r15,  // address of first argument (argv)
399      rbx   // the runtime function to call
400  };
401  data->InitializePlatformSpecific(arraysize(registers), registers);
402}
403
404void ResumeGeneratorDescriptor::InitializePlatformSpecific(
405    CallInterfaceDescriptorData* data) {
406  Register registers[] = {
407      rax,  // the value to pass to the generator
408      rbx,  // the JSGeneratorObject to resume
409      rdx   // the resume mode (tagged)
410  };
411  data->InitializePlatformSpecific(arraysize(registers), registers);
412}
413
414}  // namespace internal
415}  // namespace v8
416
417#endif  // V8_TARGET_ARCH_X64
418