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