]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGCCallHelpers.h
JavaScriptCore-1218.33.tar.gz
[apple/javascriptcore.git] / dfg / DFGCCallHelpers.h
1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef DFGCCallHelpers_h
27 #define DFGCCallHelpers_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "DFGAssemblyHelpers.h"
34 #include "DFGGPRInfo.h"
35
36 namespace JSC { namespace DFG {
37
38 class CCallHelpers : public AssemblyHelpers {
39 public:
40 CCallHelpers(VM* vm, CodeBlock* codeBlock = 0)
41 : AssemblyHelpers(vm, codeBlock)
42 {
43 }
44
45 // These methods used to sort arguments into the correct registers.
46 // On X86 we use cdecl calling conventions, which pass all arguments on the
47 // stack. On other architectures we may need to sort values into the
48 // correct registers.
49 #if !NUMBER_OF_ARGUMENT_REGISTERS
50 unsigned m_callArgumentOffset;
51 void resetCallArguments() { m_callArgumentOffset = 0; }
52
53 // These methods are using internally to implement the callOperation methods.
54 void addCallArgument(GPRReg value)
55 {
56 poke(value, m_callArgumentOffset++);
57 }
58 void addCallArgument(TrustedImm32 imm)
59 {
60 poke(imm, m_callArgumentOffset++);
61 }
62 void addCallArgument(TrustedImmPtr pointer)
63 {
64 poke(pointer, m_callArgumentOffset++);
65 }
66 void addCallArgument(FPRReg value)
67 {
68 storeDouble(value, Address(stackPointerRegister, m_callArgumentOffset * sizeof(void*)));
69 m_callArgumentOffset += sizeof(double) / sizeof(void*);
70 }
71
72 ALWAYS_INLINE void setupArguments(FPRReg arg1)
73 {
74 resetCallArguments();
75 addCallArgument(arg1);
76 }
77
78 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
79 {
80 resetCallArguments();
81 addCallArgument(arg1);
82 addCallArgument(arg2);
83 }
84
85 ALWAYS_INLINE void setupArguments(GPRReg arg1)
86 {
87 resetCallArguments();
88 addCallArgument(arg1);
89 }
90
91 ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
92 {
93 resetCallArguments();
94 addCallArgument(arg1);
95 addCallArgument(arg2);
96 }
97
98 ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1)
99 {
100 resetCallArguments();
101 addCallArgument(arg1);
102 }
103
104 ALWAYS_INLINE void setupArgumentsExecState()
105 {
106 resetCallArguments();
107 addCallArgument(GPRInfo::callFrameRegister);
108 }
109
110 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
111 {
112 resetCallArguments();
113 addCallArgument(GPRInfo::callFrameRegister);
114 addCallArgument(arg1);
115 }
116
117 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
118 {
119 resetCallArguments();
120 addCallArgument(GPRInfo::callFrameRegister);
121 addCallArgument(arg1);
122 }
123
124 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1)
125 {
126 resetCallArguments();
127 addCallArgument(GPRInfo::callFrameRegister);
128 addCallArgument(arg1);
129 }
130
131 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
132 {
133 resetCallArguments();
134 addCallArgument(GPRInfo::callFrameRegister);
135 addCallArgument(arg1);
136 addCallArgument(arg2);
137 }
138
139 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
140 {
141 resetCallArguments();
142 addCallArgument(GPRInfo::callFrameRegister);
143 addCallArgument(arg1);
144 addCallArgument(arg2);
145 }
146
147 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2)
148 {
149 resetCallArguments();
150 addCallArgument(GPRInfo::callFrameRegister);
151 addCallArgument(arg1);
152 addCallArgument(arg2);
153 }
154
155 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2)
156 {
157 resetCallArguments();
158 addCallArgument(GPRInfo::callFrameRegister);
159 addCallArgument(arg1);
160 addCallArgument(arg2);
161 }
162
163 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
164 {
165 resetCallArguments();
166 addCallArgument(GPRInfo::callFrameRegister);
167 addCallArgument(arg1);
168 addCallArgument(arg2);
169 }
170
171 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
172 {
173 resetCallArguments();
174 addCallArgument(GPRInfo::callFrameRegister);
175 addCallArgument(arg1);
176 addCallArgument(arg2);
177 }
178
179 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
180 {
181 resetCallArguments();
182 addCallArgument(GPRInfo::callFrameRegister);
183 addCallArgument(arg1);
184 addCallArgument(arg2);
185 }
186
187 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2)
188 {
189 resetCallArguments();
190 addCallArgument(GPRInfo::callFrameRegister);
191 addCallArgument(arg1);
192 addCallArgument(arg2);
193 }
194
195 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
196 {
197 resetCallArguments();
198 addCallArgument(GPRInfo::callFrameRegister);
199 addCallArgument(arg1);
200 addCallArgument(arg2);
201 addCallArgument(arg3);
202 }
203
204 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
205 {
206 resetCallArguments();
207 addCallArgument(GPRInfo::callFrameRegister);
208 addCallArgument(arg1);
209 addCallArgument(arg2);
210 addCallArgument(arg3);
211 }
212
213 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, GPRReg arg3)
214 {
215 resetCallArguments();
216 addCallArgument(GPRInfo::callFrameRegister);
217 addCallArgument(arg1);
218 addCallArgument(arg2);
219 addCallArgument(arg3);
220 }
221
222 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
223 {
224 resetCallArguments();
225 addCallArgument(GPRInfo::callFrameRegister);
226 addCallArgument(arg1);
227 addCallArgument(arg2);
228 addCallArgument(arg3);
229 }
230
231 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
232 {
233 resetCallArguments();
234 addCallArgument(GPRInfo::callFrameRegister);
235 addCallArgument(arg1);
236 addCallArgument(arg2);
237 addCallArgument(arg3);
238 }
239
240 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
241 {
242 resetCallArguments();
243 addCallArgument(GPRInfo::callFrameRegister);
244 addCallArgument(arg1);
245 addCallArgument(arg2);
246 addCallArgument(arg3);
247 }
248
249 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4)
250 {
251 resetCallArguments();
252 addCallArgument(GPRInfo::callFrameRegister);
253 addCallArgument(arg1);
254 addCallArgument(arg2);
255 addCallArgument(arg3);
256 addCallArgument(arg4);
257 }
258
259 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
260 {
261 resetCallArguments();
262 addCallArgument(GPRInfo::callFrameRegister);
263 addCallArgument(arg1);
264 addCallArgument(arg2);
265 addCallArgument(arg3);
266 addCallArgument(arg4);
267 addCallArgument(arg5);
268 }
269
270 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
271 {
272 resetCallArguments();
273 addCallArgument(GPRInfo::callFrameRegister);
274 addCallArgument(arg1);
275 addCallArgument(arg2);
276 addCallArgument(arg3);
277 addCallArgument(arg4);
278 }
279
280 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4)
281 {
282 resetCallArguments();
283 addCallArgument(GPRInfo::callFrameRegister);
284 addCallArgument(arg1);
285 addCallArgument(arg2);
286 addCallArgument(arg3);
287 addCallArgument(arg4);
288 }
289
290 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
291 {
292 resetCallArguments();
293 addCallArgument(GPRInfo::callFrameRegister);
294 addCallArgument(arg1);
295 addCallArgument(arg2);
296 addCallArgument(arg3);
297 }
298
299 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
300 {
301 resetCallArguments();
302 addCallArgument(GPRInfo::callFrameRegister);
303 addCallArgument(arg1);
304 addCallArgument(arg2);
305 addCallArgument(arg3);
306 addCallArgument(arg4);
307 }
308
309 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
310 {
311 resetCallArguments();
312 addCallArgument(GPRInfo::callFrameRegister);
313 addCallArgument(arg1);
314 addCallArgument(arg2);
315 addCallArgument(arg3);
316 addCallArgument(arg4);
317 }
318
319 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
320 {
321 resetCallArguments();
322 addCallArgument(GPRInfo::callFrameRegister);
323 addCallArgument(arg1);
324 addCallArgument(arg2);
325 addCallArgument(arg3);
326 addCallArgument(arg4);
327 }
328
329 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
330 {
331 resetCallArguments();
332 addCallArgument(GPRInfo::callFrameRegister);
333 addCallArgument(arg1);
334 addCallArgument(arg2);
335 addCallArgument(arg3);
336 addCallArgument(arg4);
337 addCallArgument(arg5);
338 }
339
340 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
341 {
342 resetCallArguments();
343 addCallArgument(GPRInfo::callFrameRegister);
344 addCallArgument(arg1);
345 addCallArgument(arg2);
346 }
347
348 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
349 {
350 resetCallArguments();
351 addCallArgument(GPRInfo::callFrameRegister);
352 addCallArgument(arg1);
353 addCallArgument(arg2);
354 addCallArgument(arg3);
355 }
356 #endif // !NUMBER_OF_ARGUMENT_REGISTERS
357 // These methods are suitable for any calling convention that provides for
358 // at least 4 argument registers, e.g. X86_64, ARMv7.
359 #if NUMBER_OF_ARGUMENT_REGISTERS >= 4
360 template<GPRReg destA, GPRReg destB>
361 void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
362 {
363 // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
364 // (1) both are already in arg regs, the right way around.
365 // (2) both are already in arg regs, the wrong way around.
366 // (3) neither are currently in arg registers.
367 // (4) srcA in in its correct reg.
368 // (5) srcA in in the incorrect reg.
369 // (6) srcB in in its correct reg.
370 // (7) srcB in in the incorrect reg.
371 //
372 // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
373 // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
374 // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
375 // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
376
377 if (srcB != destA) {
378 // Handle the easy cases - two simple moves.
379 move(srcA, destA);
380 move(srcB, destB);
381 } else if (srcA != destB) {
382 // Handle the non-swap case - just put srcB in place first.
383 move(srcB, destB);
384 move(srcA, destA);
385 } else
386 swap(destA, destB);
387 }
388 #if CPU(X86_64) || CPU(ARM64)
389 template<FPRReg destA, FPRReg destB>
390 void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
391 {
392 // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
393 // (1) both are already in arg regs, the right way around.
394 // (2) both are already in arg regs, the wrong way around.
395 // (3) neither are currently in arg registers.
396 // (4) srcA in in its correct reg.
397 // (5) srcA in in the incorrect reg.
398 // (6) srcB in in its correct reg.
399 // (7) srcB in in the incorrect reg.
400 //
401 // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
402 // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
403 // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
404 // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
405
406 if (srcB != destA) {
407 // Handle the easy cases - two simple moves.
408 moveDouble(srcA, destA);
409 moveDouble(srcB, destB);
410 return;
411 }
412
413 if (srcA != destB) {
414 // Handle the non-swap case - just put srcB in place first.
415 moveDouble(srcB, destB);
416 moveDouble(srcA, destA);
417 return;
418 }
419
420 ASSERT(srcB == destA && srcA == destB);
421 // Need to swap; pick a temporary register.
422 FPRReg temp;
423 if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
424 temp = FPRInfo::argumentFPR3;
425 else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
426 temp = FPRInfo::argumentFPR2;
427 else {
428 ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
429 temp = FPRInfo::argumentFPR1;
430 }
431 moveDouble(destA, temp);
432 moveDouble(destB, destA);
433 moveDouble(temp, destB);
434 }
435 #endif
436 void setupStubArguments(GPRReg arg1, GPRReg arg2)
437 {
438 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
439 }
440 void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
441 {
442 // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
443 // Then we can use setupTwoStubArgs to fix arg2/arg3.
444 if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
445 move(arg1, GPRInfo::argumentGPR1);
446 setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
447 return;
448 }
449
450 // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
451 // Then we can use setupTwoStubArgs to fix arg1/arg3.
452 if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
453 move(arg2, GPRInfo::argumentGPR2);
454 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
455 return;
456 }
457
458 // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
459 // Then we can use setupTwoStubArgs to fix arg1/arg2.
460 if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
461 move(arg3, GPRInfo::argumentGPR3);
462 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
463 return;
464 }
465
466 // If we get here, we haven't been able to move any of arg1/arg2/arg3.
467 // Since all three are blocked, then all three must already be in the argument register.
468 // But are they in the right ones?
469
470 // First, ensure arg1 is in place.
471 if (arg1 != GPRInfo::argumentGPR1) {
472 swap(arg1, GPRInfo::argumentGPR1);
473
474 // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
475 ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
476 // If arg2 was in argumentGPR1 it no longer is (due to the swap).
477 // Otherwise arg3 must have been. Mark him as moved.
478 if (arg2 == GPRInfo::argumentGPR1)
479 arg2 = arg1;
480 else
481 arg3 = arg1;
482 }
483
484 // Either arg2 & arg3 need swapping, or we're all done.
485 ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
486 || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
487
488 if (arg2 != GPRInfo::argumentGPR2)
489 swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
490 }
491
492 #if CPU(X86_64) || CPU(ARM64)
493 ALWAYS_INLINE void setupArguments(FPRReg arg1)
494 {
495 moveDouble(arg1, FPRInfo::argumentFPR0);
496 }
497
498 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
499 {
500 setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
501 }
502
503 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
504 {
505 moveDouble(arg1, FPRInfo::argumentFPR0);
506 move(arg2, GPRInfo::argumentGPR1);
507 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
508 }
509
510 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
511 {
512 moveDouble(arg3, FPRInfo::argumentFPR0);
513 setupStubArguments(arg1, arg2);
514 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
515 }
516 #elif CPU(ARM)
517 #if CPU(ARM_HARDFP)
518 ALWAYS_INLINE void setupArguments(FPRReg arg1)
519 {
520 moveDouble(arg1, FPRInfo::argumentFPR0);
521 }
522
523 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
524 {
525 if (arg2 != FPRInfo::argumentFPR0) {
526 moveDouble(arg1, FPRInfo::argumentFPR0);
527 moveDouble(arg2, FPRInfo::argumentFPR1);
528 } else if (arg1 != FPRInfo::argumentFPR1) {
529 moveDouble(arg2, FPRInfo::argumentFPR1);
530 moveDouble(arg1, FPRInfo::argumentFPR0);
531 } else {
532 // Swap arg1, arg2.
533 moveDouble(FPRInfo::argumentFPR0, ARMRegisters::d2);
534 moveDouble(FPRInfo::argumentFPR1, FPRInfo::argumentFPR0);
535 moveDouble(ARMRegisters::d2, FPRInfo::argumentFPR1);
536 }
537 }
538
539 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
540 {
541 moveDouble(arg1, FPRInfo::argumentFPR0);
542 move(arg2, GPRInfo::argumentGPR1);
543 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
544 }
545
546 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
547 {
548 moveDouble(arg3, FPRInfo::argumentFPR0);
549 setupStubArguments(arg1, arg2);
550 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
551 }
552 #else
553 ALWAYS_INLINE void setupArguments(FPRReg arg1)
554 {
555 assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
556 }
557
558 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
559 {
560 assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
561 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
562 }
563
564 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
565 {
566 move(arg2, GPRInfo::argumentGPR3);
567 assembler().vmov(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, arg1);
568 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
569 }
570
571 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
572 {
573 setupStubArguments(arg1, arg2);
574 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
575 assembler().vmov(GPRInfo::argumentGPR3, GPRInfo::nonArgGPR0, arg3);
576 poke(GPRInfo::nonArgGPR0);
577 }
578 #endif // CPU(ARM_HARDFP)
579 #elif CPU(MIPS)
580 ALWAYS_INLINE void setupArguments(FPRReg arg1)
581 {
582 moveDouble(arg1, FPRInfo::argumentFPR0);
583 }
584
585 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
586 {
587 if (arg2 != FPRInfo::argumentFPR0) {
588 moveDouble(arg1, FPRInfo::argumentFPR0);
589 moveDouble(arg2, FPRInfo::argumentFPR1);
590 } else if (arg1 != FPRInfo::argumentFPR1) {
591 moveDouble(arg2, FPRInfo::argumentFPR1);
592 moveDouble(arg1, FPRInfo::argumentFPR0);
593 } else {
594 // Swap arg1, arg2.
595 swapDouble(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1);
596 }
597 }
598
599 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
600 {
601 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1);
602 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
603 poke(arg2, 4);
604 }
605
606 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
607 {
608 setupStubArguments(arg1, arg2);
609 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
610 poke(arg3, 4);
611 }
612 #else
613 #error "DFG JIT not supported on this platform."
614 #endif
615
616 ALWAYS_INLINE void setupArguments(GPRReg arg1)
617 {
618 move(arg1, GPRInfo::argumentGPR0);
619 }
620
621 ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
622 {
623 setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
624 }
625
626 ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1)
627 {
628 move(arg1, GPRInfo::argumentGPR0);
629 }
630
631 ALWAYS_INLINE void setupArgumentsExecState()
632 {
633 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
634 }
635
636 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
637 {
638 move(arg1, GPRInfo::argumentGPR1);
639 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
640 }
641
642 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
643 {
644 move(arg1, GPRInfo::argumentGPR1);
645 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
646 }
647
648 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1)
649 {
650 move(arg1, GPRInfo::argumentGPR1);
651 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
652 }
653
654 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
655 {
656 setupStubArguments(arg1, arg2);
657 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
658 }
659
660 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
661 {
662 move(arg1, GPRInfo::argumentGPR1);
663 move(arg2, GPRInfo::argumentGPR2);
664 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
665 }
666 #if CPU(X86_64) || CPU(ARM64)
667 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm64 arg2)
668 {
669 move(arg1, GPRInfo::argumentGPR1);
670 move(arg2, GPRInfo::argumentGPR2);
671 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
672 }
673
674 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm64 arg1, GPRReg arg2)
675 {
676 move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
677 move(arg1, GPRInfo::argumentGPR1);
678 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
679 }
680 #endif
681 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2)
682 {
683 move(arg1, GPRInfo::argumentGPR1);
684 move(arg2, GPRInfo::argumentGPR2);
685 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
686 }
687
688 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, ImmPtr arg2)
689 {
690 move(arg1, GPRInfo::argumentGPR1);
691 move(arg2, GPRInfo::argumentGPR2);
692 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
693 }
694
695 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
696 {
697 move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
698 move(arg1, GPRInfo::argumentGPR1);
699 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
700 }
701
702 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2)
703 {
704 move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
705 move(arg1, GPRInfo::argumentGPR1);
706 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
707 }
708
709 ALWAYS_INLINE void setupArgumentsWithExecState(ImmPtr arg1, GPRReg arg2)
710 {
711 move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
712 move(arg1, GPRInfo::argumentGPR1);
713 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
714 }
715
716 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
717 {
718 move(arg1, GPRInfo::argumentGPR1);
719 move(arg2, GPRInfo::argumentGPR2);
720 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
721 }
722
723 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
724 {
725 move(arg1, GPRInfo::argumentGPR1);
726 move(arg2, GPRInfo::argumentGPR2);
727 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
728 }
729
730 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2)
731 {
732 move(arg1, GPRInfo::argumentGPR1);
733 move(arg2, GPRInfo::argumentGPR2);
734 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
735 }
736
737 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
738 {
739 setupStubArguments(arg1, arg2, arg3);
740 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
741 }
742
743 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
744 {
745 setupStubArguments(arg1, arg2);
746 move(arg3, GPRInfo::argumentGPR3);
747 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
748 }
749
750 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, GPRReg arg3)
751 {
752 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
753 move(arg2, GPRInfo::argumentGPR2);
754 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
755 }
756
757 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
758 {
759 move(arg1, GPRInfo::argumentGPR1);
760 move(arg2, GPRInfo::argumentGPR2);
761 move(arg3, GPRInfo::argumentGPR3);
762 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
763 }
764
765 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3)
766 {
767 move(arg1, GPRInfo::argumentGPR1);
768 move(arg2, GPRInfo::argumentGPR2);
769 move(arg3, GPRInfo::argumentGPR3);
770 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
771 }
772
773 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
774 {
775 move(arg1, GPRInfo::argumentGPR1);
776 move(arg2, GPRInfo::argumentGPR2);
777 move(arg3, GPRInfo::argumentGPR3);
778 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
779 }
780
781 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
782 {
783 setupStubArguments(arg1, arg2);
784 move(arg3, GPRInfo::argumentGPR3);
785 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
786 }
787
788 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
789 {
790 move(arg3, GPRInfo::argumentGPR3);
791 move(arg1, GPRInfo::argumentGPR1);
792 move(arg2, GPRInfo::argumentGPR2);
793 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
794 }
795
796 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
797 {
798 move(arg3, GPRInfo::argumentGPR3);
799 move(arg1, GPRInfo::argumentGPR1);
800 move(arg2, GPRInfo::argumentGPR2);
801 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
802 }
803
804 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3)
805 {
806 move(arg2, GPRInfo::argumentGPR2);
807 move(arg1, GPRInfo::argumentGPR1);
808 move(arg3, GPRInfo::argumentGPR3);
809 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
810 }
811
812 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3)
813 {
814 setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
815 move(arg1, GPRInfo::argumentGPR1);
816 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
817 }
818
819 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
820 {
821 move(arg1, GPRInfo::argumentGPR1);
822 move(arg2, GPRInfo::argumentGPR2);
823 move(arg3, GPRInfo::argumentGPR3);
824 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
825 }
826
827 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3)
828 {
829 move(arg1, GPRInfo::argumentGPR1);
830 move(arg2, GPRInfo::argumentGPR2);
831 move(arg3, GPRInfo::argumentGPR3);
832 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
833 }
834
835 #endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
836 // These methods are suitable for any calling convention that provides for
837 // exactly 4 argument registers, e.g. ARMv7.
838 #if NUMBER_OF_ARGUMENT_REGISTERS == 4
839
840 #if CPU(MIPS)
841 #define POKE_ARGUMENT_OFFSET 4
842 #else
843 #define POKE_ARGUMENT_OFFSET 0
844 #endif
845
846 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
847 {
848 poke(arg4, POKE_ARGUMENT_OFFSET);
849 setupArgumentsWithExecState(arg1, arg2, arg3);
850 }
851
852 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4)
853 {
854 poke(arg4, POKE_ARGUMENT_OFFSET);
855 setupArgumentsWithExecState(arg1, arg2, arg3);
856 }
857
858 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4)
859 {
860 poke(arg4, POKE_ARGUMENT_OFFSET);
861 setupArgumentsWithExecState(arg1, arg2, arg3);
862 }
863
864 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
865 {
866 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
867 poke(arg4, POKE_ARGUMENT_OFFSET);
868 setupArgumentsWithExecState(arg1, arg2, arg3);
869 }
870
871 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
872 {
873 poke(arg4, POKE_ARGUMENT_OFFSET);
874 setupArgumentsWithExecState(arg1, arg2, arg3);
875 }
876
877 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
878 {
879 poke(arg4, POKE_ARGUMENT_OFFSET);
880 setupArgumentsWithExecState(arg1, arg2, arg3);
881 }
882
883 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
884 {
885 poke(arg4, POKE_ARGUMENT_OFFSET);
886 setupArgumentsWithExecState(arg1, arg2, arg3);
887 }
888
889 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
890 {
891 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
892 poke(arg4, POKE_ARGUMENT_OFFSET);
893 setupArgumentsWithExecState(arg1, arg2, arg3);
894 }
895
896 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
897 {
898 poke(arg4, POKE_ARGUMENT_OFFSET);
899 setupArgumentsWithExecState(arg1, arg2, arg3);
900 }
901
902 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
903 {
904 poke(arg4, POKE_ARGUMENT_OFFSET);
905 setupArgumentsWithExecState(arg1, arg2, arg3);
906 }
907
908 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImmPtr arg4)
909 {
910 poke(arg4, POKE_ARGUMENT_OFFSET);
911 setupArgumentsWithExecState(arg1, arg2, arg3);
912 }
913
914 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
915 {
916 poke(arg4, POKE_ARGUMENT_OFFSET);
917 setupArgumentsWithExecState(arg1, arg2, arg3);
918 }
919
920 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
921 {
922 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
923 poke(arg4, POKE_ARGUMENT_OFFSET);
924 setupArgumentsWithExecState(arg1, arg2, arg3);
925 }
926
927 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, TrustedImm32 arg5)
928 {
929 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
930 poke(arg4, POKE_ARGUMENT_OFFSET);
931 setupArgumentsWithExecState(arg1, arg2, arg3);
932 }
933
934 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5)
935 {
936 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
937 poke(arg4, POKE_ARGUMENT_OFFSET);
938 setupArgumentsWithExecState(arg1, arg2, arg3);
939 }
940
941 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, TrustedImm32 arg5)
942 {
943 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
944 poke(arg4, POKE_ARGUMENT_OFFSET);
945 setupArgumentsWithExecState(arg1, arg2, arg3);
946 }
947
948 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
949 {
950 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
951 poke(arg4, POKE_ARGUMENT_OFFSET);
952 setupArgumentsWithExecState(arg1, arg2, arg3);
953 }
954
955 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
956 {
957 poke(arg5, POKE_ARGUMENT_OFFSET + 1);
958 poke(arg4, POKE_ARGUMENT_OFFSET);
959 setupArgumentsWithExecState(arg1, arg2, arg3);
960 }
961
962 #endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
963
964 #if NUMBER_OF_ARGUMENT_REGISTERS >= 5
965 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4)
966 {
967 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR4>(arg1, arg4);
968 move(arg2, GPRInfo::argumentGPR2);
969 move(arg3, GPRInfo::argumentGPR3);
970 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
971 }
972 #endif
973
974 void setupResults(GPRReg destA, GPRReg destB)
975 {
976 GPRReg srcA = GPRInfo::returnValueGPR;
977 GPRReg srcB = GPRInfo::returnValueGPR2;
978
979 if (srcB != destA) {
980 // Handle the easy cases - two simple moves.
981 move(srcA, destA);
982 move(srcB, destB);
983 } else if (srcA != destB) {
984 // Handle the non-swap case - just put srcB in place first.
985 move(srcB, destB);
986 move(srcA, destA);
987 } else
988 swap(destA, destB);
989 }
990 };
991
992 } } // namespace JSC::DFG
993
994 #endif // ENABLE(DFG_JIT)
995
996 #endif // DFGCCallHelpers_h
997