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