5bc45d8e62c1ce395111545a1185283fb2226a3a
[WebKit-https.git] / Source / JavaScriptCore / 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(JSGlobalData* globalData, CodeBlock* codeBlock)
41         : AssemblyHelpers(globalData, 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 setupArgumentsExecState()
99     {
100         resetCallArguments();
101         addCallArgument(GPRInfo::callFrameRegister);
102     }
103
104     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
105     {
106         resetCallArguments();
107         addCallArgument(GPRInfo::callFrameRegister);
108         addCallArgument(arg1);
109     }
110
111     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
112     {
113         resetCallArguments();
114         addCallArgument(GPRInfo::callFrameRegister);
115         addCallArgument(arg1);
116     }
117
118     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1)
119     {
120         resetCallArguments();
121         addCallArgument(GPRInfo::callFrameRegister);
122         addCallArgument(arg1);
123     }
124
125     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
126     {
127         resetCallArguments();
128         addCallArgument(GPRInfo::callFrameRegister);
129         addCallArgument(arg1);
130         addCallArgument(arg2);
131     }
132
133     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
134     {
135         resetCallArguments();
136         addCallArgument(GPRInfo::callFrameRegister);
137         addCallArgument(arg1);
138         addCallArgument(arg2);
139     }
140
141     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2)
142     {
143         resetCallArguments();
144         addCallArgument(GPRInfo::callFrameRegister);
145         addCallArgument(arg1);
146         addCallArgument(arg2);
147     }
148
149     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2)
150     {
151         resetCallArguments();
152         addCallArgument(GPRInfo::callFrameRegister);
153         addCallArgument(arg1);
154         addCallArgument(arg2);
155     }
156
157     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
158     {
159         resetCallArguments();
160         addCallArgument(GPRInfo::callFrameRegister);
161         addCallArgument(arg1);
162         addCallArgument(arg2);
163     }
164
165     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
166     {
167         resetCallArguments();
168         addCallArgument(GPRInfo::callFrameRegister);
169         addCallArgument(arg1);
170         addCallArgument(arg2);
171     }
172
173     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
174     {
175         resetCallArguments();
176         addCallArgument(GPRInfo::callFrameRegister);
177         addCallArgument(arg1);
178         addCallArgument(arg2);
179         addCallArgument(arg3);
180     }
181
182     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
183     {
184         resetCallArguments();
185         addCallArgument(GPRInfo::callFrameRegister);
186         addCallArgument(arg1);
187         addCallArgument(arg2);
188         addCallArgument(arg3);
189     }
190
191     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
192     {
193         resetCallArguments();
194         addCallArgument(GPRInfo::callFrameRegister);
195         addCallArgument(arg1);
196         addCallArgument(arg2);
197         addCallArgument(arg3);
198     }
199
200     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
201     {
202         resetCallArguments();
203         addCallArgument(GPRInfo::callFrameRegister);
204         addCallArgument(arg1);
205         addCallArgument(arg2);
206         addCallArgument(arg3);
207     }
208
209     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
210     {
211         resetCallArguments();
212         addCallArgument(GPRInfo::callFrameRegister);
213         addCallArgument(arg1);
214         addCallArgument(arg2);
215         addCallArgument(arg3);
216         addCallArgument(arg4);
217     }
218
219     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
220     {
221         resetCallArguments();
222         addCallArgument(GPRInfo::callFrameRegister);
223         addCallArgument(arg1);
224         addCallArgument(arg2);
225         addCallArgument(arg3);
226     }
227
228     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
229     {
230         resetCallArguments();
231         addCallArgument(GPRInfo::callFrameRegister);
232         addCallArgument(arg1);
233         addCallArgument(arg2);
234         addCallArgument(arg3);
235         addCallArgument(arg4);
236     }
237
238     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
239     {
240         resetCallArguments();
241         addCallArgument(GPRInfo::callFrameRegister);
242         addCallArgument(arg1);
243         addCallArgument(arg2);
244         addCallArgument(arg3);
245         addCallArgument(arg4);
246     }
247
248     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
249     {
250         resetCallArguments();
251         addCallArgument(GPRInfo::callFrameRegister);
252         addCallArgument(arg1);
253         addCallArgument(arg2);
254         addCallArgument(arg3);
255         addCallArgument(arg4);
256     }
257
258     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
259     {
260         resetCallArguments();
261         addCallArgument(GPRInfo::callFrameRegister);
262         addCallArgument(arg1);
263         addCallArgument(arg2);
264         addCallArgument(arg3);
265         addCallArgument(arg4);
266         addCallArgument(arg5);
267     }
268 #endif // !NUMBER_OF_ARGUMENT_REGISTERS
269     // These methods are suitable for any calling convention that provides for
270     // at least 4 argument registers, e.g. X86_64, ARMv7.
271 #if NUMBER_OF_ARGUMENT_REGISTERS >= 4
272     template<GPRReg destA, GPRReg destB>
273     void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
274     {
275         // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
276         // (1) both are already in arg regs, the right way around.
277         // (2) both are already in arg regs, the wrong way around.
278         // (3) neither are currently in arg registers.
279         // (4) srcA in in its correct reg.
280         // (5) srcA in in the incorrect reg.
281         // (6) srcB in in its correct reg.
282         // (7) srcB in in the incorrect reg.
283         //
284         // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
285         // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
286         // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
287         // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
288
289         if (srcB != destA) {
290             // Handle the easy cases - two simple moves.
291             move(srcA, destA);
292             move(srcB, destB);
293         } else if (srcA != destB) {
294             // Handle the non-swap case - just put srcB in place first.
295             move(srcB, destB);
296             move(srcA, destA);
297         } else
298             swap(destA, destB);
299     }
300 #if CPU(X86_64)
301     template<FPRReg destA, FPRReg destB>
302     void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
303     {
304         // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
305         // (1) both are already in arg regs, the right way around.
306         // (2) both are already in arg regs, the wrong way around.
307         // (3) neither are currently in arg registers.
308         // (4) srcA in in its correct reg.
309         // (5) srcA in in the incorrect reg.
310         // (6) srcB in in its correct reg.
311         // (7) srcB in in the incorrect reg.
312         //
313         // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
314         // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
315         // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
316         // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
317
318         if (srcB != destA) {
319             // Handle the easy cases - two simple moves.
320             moveDouble(srcA, destA);
321             moveDouble(srcB, destB);
322             return;
323         }
324         
325         if (srcA != destB) {
326             // Handle the non-swap case - just put srcB in place first.
327             moveDouble(srcB, destB);
328             moveDouble(srcA, destA);
329             return;
330         }
331
332         ASSERT(srcB == destA && srcA == destB);
333         // Need to swap; pick a temporary register.
334         FPRReg temp;
335         if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
336             temp = FPRInfo::argumentFPR3;
337         else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
338             temp = FPRInfo::argumentFPR2;
339         else {
340             ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
341             temp = FPRInfo::argumentFPR1;
342         }
343         moveDouble(destA, temp);
344         moveDouble(destB, destA);
345         moveDouble(temp, destB);
346     }
347 #endif
348     void setupStubArguments(GPRReg arg1, GPRReg arg2)
349     {
350         setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
351     }
352     void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
353     {
354         // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
355         // Then we can use setupTwoStubArgs to fix arg2/arg3.
356         if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
357             move(arg1, GPRInfo::argumentGPR1);
358             setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
359             return;
360         }
361
362         // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
363         // Then we can use setupTwoStubArgs to fix arg1/arg3.
364         if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
365             move(arg2, GPRInfo::argumentGPR2);
366             setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
367             return;
368         }
369
370         // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
371         // Then we can use setupTwoStubArgs to fix arg1/arg2.
372         if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
373             move(arg3, GPRInfo::argumentGPR3);
374             setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
375             return;
376         }
377
378         // If we get here, we haven't been able to move any of arg1/arg2/arg3.
379         // Since all three are blocked, then all three must already be in the argument register.
380         // But are they in the right ones?
381
382         // First, ensure arg1 is in place.
383         if (arg1 != GPRInfo::argumentGPR1) {
384             swap(arg1, GPRInfo::argumentGPR1);
385
386             // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
387             ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
388             // If arg2 was in argumentGPR1 it no longer is (due to the swap).
389             // Otherwise arg3 must have been. Mark him as moved.
390             if (arg2 == GPRInfo::argumentGPR1)
391                 arg2 = arg1;
392             else
393                 arg3 = arg1;
394         }
395
396         // Either arg2 & arg3 need swapping, or we're all done.
397         ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
398             || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
399
400         if (arg2 != GPRInfo::argumentGPR2)
401             swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
402     }
403
404 #if CPU(X86_64)
405     ALWAYS_INLINE void setupArguments(FPRReg arg1)
406     {
407         moveDouble(arg1, FPRInfo::argumentFPR0);
408     }
409
410     ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
411     {
412         setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
413     }
414 #else
415     ALWAYS_INLINE void setupArguments(FPRReg arg1)
416     {
417         assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
418     }
419
420     ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
421     {
422         assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
423         assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
424     }
425 #endif
426
427     ALWAYS_INLINE void setupArguments(GPRReg arg1)
428     {
429         move(arg1, GPRInfo::argumentGPR0);
430     }
431
432     ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
433     {
434         setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
435     }
436
437     ALWAYS_INLINE void setupArgumentsExecState()
438     {
439         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
440     }
441
442     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
443     {
444         move(arg1, GPRInfo::argumentGPR1);
445         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
446     }
447
448     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
449     {
450         move(arg1, GPRInfo::argumentGPR1);
451         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
452     }
453
454     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1)
455     {
456         move(arg1, GPRInfo::argumentGPR1);
457         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
458     }
459
460     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
461     {
462         setupStubArguments(arg1, arg2);
463         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
464     }
465
466     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
467     {
468         move(arg1, GPRInfo::argumentGPR1);
469         move(arg2, GPRInfo::argumentGPR2);
470         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
471     }
472     
473     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2)
474     {
475         move(arg1, GPRInfo::argumentGPR1);
476         move(arg2, GPRInfo::argumentGPR2);
477         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
478     }
479     
480     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, ImmPtr arg2)
481     {
482         move(arg1, GPRInfo::argumentGPR1);
483         move(arg2, GPRInfo::argumentGPR2);
484         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
485     }
486
487     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
488     {
489         move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
490         move(arg1, GPRInfo::argumentGPR1);
491         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
492     }
493     
494     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2)
495     {
496         move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
497         move(arg1, GPRInfo::argumentGPR1);
498         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
499     }
500     
501     ALWAYS_INLINE void setupArgumentsWithExecState(ImmPtr arg1, GPRReg arg2)
502     {
503         move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
504         move(arg1, GPRInfo::argumentGPR1);
505         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
506     }
507
508     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
509     {
510         move(arg1, GPRInfo::argumentGPR1);
511         move(arg2, GPRInfo::argumentGPR2);
512         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
513     }
514
515     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
516     {
517         move(arg1, GPRInfo::argumentGPR1);
518         move(arg2, GPRInfo::argumentGPR2);
519         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
520     }
521
522     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
523     {
524         setupStubArguments(arg1, arg2, arg3);
525         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
526     }
527
528     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
529     {
530         setupStubArguments(arg1, arg2);
531         move(arg3, GPRInfo::argumentGPR3);
532         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
533     }
534
535     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
536     {
537         move(arg1, GPRInfo::argumentGPR1);
538         move(arg2, GPRInfo::argumentGPR2);
539         move(arg3, GPRInfo::argumentGPR3);
540         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
541     }
542
543     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
544     {
545         move(arg1, GPRInfo::argumentGPR1);
546         move(arg2, GPRInfo::argumentGPR2);
547         move(arg3, GPRInfo::argumentGPR3);
548         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
549     }
550
551     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
552     {
553         setupStubArguments(arg1, arg2);
554         move(arg3, GPRInfo::argumentGPR3);
555         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
556     }
557
558     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
559     {
560         move(arg3, GPRInfo::argumentGPR3);
561         move(arg1, GPRInfo::argumentGPR1);
562         move(arg2, GPRInfo::argumentGPR2);
563         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
564     }
565
566     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
567     {
568         move(arg3, GPRInfo::argumentGPR3);
569         move(arg1, GPRInfo::argumentGPR1);
570         move(arg2, GPRInfo::argumentGPR2);
571         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
572     }
573
574     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3)
575     {
576         move(arg2, GPRInfo::argumentGPR2);
577         move(arg1, GPRInfo::argumentGPR1);
578         move(arg3, GPRInfo::argumentGPR3);
579         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
580     }
581
582     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3)
583     {
584         setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
585         move(arg1, GPRInfo::argumentGPR1);
586         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
587     }
588
589     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3)
590     {
591         move(arg1, GPRInfo::argumentGPR1);
592         move(arg2, GPRInfo::argumentGPR2);
593         move(arg3, GPRInfo::argumentGPR3);
594         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
595     }
596
597 #endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
598     // These methods are suitable for any calling convention that provides for
599     // exactly 4 argument registers, e.g. ARMv7.
600 #if NUMBER_OF_ARGUMENT_REGISTERS == 4
601     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
602     {
603         poke(arg4);
604         setupArgumentsWithExecState(arg1, arg2, arg3);
605     }
606
607     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
608     {
609         poke(arg4);
610         setupArgumentsWithExecState(arg1, arg2, arg3);
611     }
612
613     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
614     {
615         poke(arg4);
616         setupArgumentsWithExecState(arg1, arg2, arg3);
617     }
618
619     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
620     {
621         poke(arg4);
622         setupArgumentsWithExecState(arg1, arg2, arg3);
623     }
624
625     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
626     {
627         poke(arg5, 1);
628         poke(arg4);
629         setupArgumentsWithExecState(arg1, arg2, arg3);
630     }
631
632     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
633     {
634         poke(arg4);
635         setupArgumentsWithExecState(arg1, arg2, arg3);
636     }
637
638     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
639     {
640         poke(arg4);
641         setupArgumentsWithExecState(arg1, arg2, arg3);
642     }
643
644     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImmPtr arg4)
645     {
646         poke(arg4);
647         setupArgumentsWithExecState(arg1, arg2, arg3);
648     }
649
650     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
651     {
652         poke(arg5, 1);
653         poke(arg4);
654         setupArgumentsWithExecState(arg1, arg2, arg3);
655     }
656
657     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5)
658     {
659         poke(arg5, 1);
660         poke(arg4);
661         setupArgumentsWithExecState(arg1, arg2, arg3);
662     }
663
664     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, TrustedImm32 arg5)
665     {
666         poke(arg5, 1);
667         poke(arg4);
668         setupArgumentsWithExecState(arg1, arg2, arg3);
669     }
670
671     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
672     {
673         poke(arg5, 1);
674         poke(arg4);
675         setupArgumentsWithExecState(arg1, arg2, arg3);
676     }
677
678     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
679     {
680         poke(arg5, 1);
681         poke(arg4);
682         setupArgumentsWithExecState(arg1, arg2, arg3);
683     }
684
685 #endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
686
687     void setupResults(GPRReg destA, GPRReg destB)
688     {
689         GPRReg srcA = GPRInfo::returnValueGPR;
690         GPRReg srcB = GPRInfo::returnValueGPR2;
691
692         if (srcB != destA) {
693             // Handle the easy cases - two simple moves.
694             move(srcA, destA);
695             move(srcB, destB);
696         } else if (srcA != destB) {
697             // Handle the non-swap case - just put srcB in place first.
698             move(srcB, destB);
699             move(srcA, destA);
700         } else
701             swap(destA, destB);
702     }
703 };
704
705 } } // namespace JSC::DFG
706
707 #endif // ENABLE(DFG_JIT)
708
709 #endif // DFGCCallHelpers_h
710