]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGCCallHelpers.h
JavaScriptCore-1097.3.3.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(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(GPRReg arg1, GPRReg arg2)
119 {
120 resetCallArguments();
121 addCallArgument(GPRInfo::callFrameRegister);
122 addCallArgument(arg1);
123 addCallArgument(arg2);
124 }
125
126 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
127 {
128 resetCallArguments();
129 addCallArgument(GPRInfo::callFrameRegister);
130 addCallArgument(arg1);
131 addCallArgument(arg2);
132 }
133
134 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
135 {
136 resetCallArguments();
137 addCallArgument(GPRInfo::callFrameRegister);
138 addCallArgument(arg1);
139 addCallArgument(arg2);
140 }
141
142 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
143 {
144 resetCallArguments();
145 addCallArgument(GPRInfo::callFrameRegister);
146 addCallArgument(arg1);
147 addCallArgument(arg2);
148 }
149
150 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
151 {
152 resetCallArguments();
153 addCallArgument(GPRInfo::callFrameRegister);
154 addCallArgument(arg1);
155 addCallArgument(arg2);
156 addCallArgument(arg3);
157 }
158
159 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
160 {
161 resetCallArguments();
162 addCallArgument(GPRInfo::callFrameRegister);
163 addCallArgument(arg1);
164 addCallArgument(arg2);
165 addCallArgument(arg3);
166 }
167
168 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
169 {
170 resetCallArguments();
171 addCallArgument(GPRInfo::callFrameRegister);
172 addCallArgument(arg1);
173 addCallArgument(arg2);
174 addCallArgument(arg3);
175 }
176
177 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
178 {
179 resetCallArguments();
180 addCallArgument(GPRInfo::callFrameRegister);
181 addCallArgument(arg1);
182 addCallArgument(arg2);
183 addCallArgument(arg3);
184 }
185
186 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
187 {
188 resetCallArguments();
189 addCallArgument(GPRInfo::callFrameRegister);
190 addCallArgument(arg1);
191 addCallArgument(arg2);
192 addCallArgument(arg3);
193 addCallArgument(arg4);
194 }
195
196 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
197 {
198 resetCallArguments();
199 addCallArgument(GPRInfo::callFrameRegister);
200 addCallArgument(arg1);
201 addCallArgument(arg2);
202 addCallArgument(arg3);
203 addCallArgument(arg4);
204 }
205
206 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
207 {
208 resetCallArguments();
209 addCallArgument(GPRInfo::callFrameRegister);
210 addCallArgument(arg1);
211 addCallArgument(arg2);
212 addCallArgument(arg3);
213 addCallArgument(arg4);
214 }
215
216 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
217 {
218 resetCallArguments();
219 addCallArgument(GPRInfo::callFrameRegister);
220 addCallArgument(arg1);
221 addCallArgument(arg2);
222 addCallArgument(arg3);
223 addCallArgument(arg4);
224 }
225
226 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
227 {
228 resetCallArguments();
229 addCallArgument(GPRInfo::callFrameRegister);
230 addCallArgument(arg1);
231 addCallArgument(arg2);
232 addCallArgument(arg3);
233 addCallArgument(arg4);
234 addCallArgument(arg5);
235 }
236 #endif // !NUMBER_OF_ARGUMENT_REGISTERS
237 // These methods are suitable for any calling convention that provides for
238 // at least 4 argument registers, e.g. X86_64, ARMv7.
239 #if NUMBER_OF_ARGUMENT_REGISTERS >= 4
240 template<GPRReg destA, GPRReg destB>
241 void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
242 {
243 // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
244 // (1) both are already in arg regs, the right way around.
245 // (2) both are already in arg regs, the wrong way around.
246 // (3) neither are currently in arg registers.
247 // (4) srcA in in its correct reg.
248 // (5) srcA in in the incorrect reg.
249 // (6) srcB in in its correct reg.
250 // (7) srcB in in the incorrect reg.
251 //
252 // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
253 // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
254 // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
255 // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
256
257 if (srcB != destA) {
258 // Handle the easy cases - two simple moves.
259 move(srcA, destA);
260 move(srcB, destB);
261 } else if (srcA != destB) {
262 // Handle the non-swap case - just put srcB in place first.
263 move(srcB, destB);
264 move(srcA, destA);
265 } else
266 swap(destA, destB);
267 }
268 #if CPU(X86_64)
269 template<FPRReg destA, FPRReg destB>
270 void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
271 {
272 // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
273 // (1) both are already in arg regs, the right way around.
274 // (2) both are already in arg regs, the wrong way around.
275 // (3) neither are currently in arg registers.
276 // (4) srcA in in its correct reg.
277 // (5) srcA in in the incorrect reg.
278 // (6) srcB in in its correct reg.
279 // (7) srcB in in the incorrect reg.
280 //
281 // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
282 // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
283 // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
284 // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
285
286 if (srcB != destA) {
287 // Handle the easy cases - two simple moves.
288 moveDouble(srcA, destA);
289 moveDouble(srcB, destB);
290 return;
291 }
292
293 if (srcA != destB) {
294 // Handle the non-swap case - just put srcB in place first.
295 moveDouble(srcB, destB);
296 moveDouble(srcA, destA);
297 return;
298 }
299
300 ASSERT(srcB == destA && srcA == destB);
301 // Need to swap; pick a temporary register.
302 FPRReg temp;
303 if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
304 temp = FPRInfo::argumentFPR3;
305 else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
306 temp = FPRInfo::argumentFPR2;
307 else {
308 ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
309 temp = FPRInfo::argumentFPR1;
310 }
311 moveDouble(destA, temp);
312 moveDouble(destB, destA);
313 moveDouble(temp, destB);
314 }
315 #endif
316 void setupStubArguments(GPRReg arg1, GPRReg arg2)
317 {
318 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
319 }
320 void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
321 {
322 // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
323 // Then we can use setupTwoStubArgs to fix arg2/arg3.
324 if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
325 move(arg1, GPRInfo::argumentGPR1);
326 setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
327 return;
328 }
329
330 // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
331 // Then we can use setupTwoStubArgs to fix arg1/arg3.
332 if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
333 move(arg2, GPRInfo::argumentGPR2);
334 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
335 return;
336 }
337
338 // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
339 // Then we can use setupTwoStubArgs to fix arg1/arg2.
340 if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
341 move(arg3, GPRInfo::argumentGPR3);
342 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
343 return;
344 }
345
346 // If we get here, we haven't been able to move any of arg1/arg2/arg3.
347 // Since all three are blocked, then all three must already be in the argument register.
348 // But are they in the right ones?
349
350 // First, ensure arg1 is in place.
351 if (arg1 != GPRInfo::argumentGPR1) {
352 swap(arg1, GPRInfo::argumentGPR1);
353
354 // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
355 ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
356 // If arg2 was in argumentGPR1 it no longer is (due to the swap).
357 // Otherwise arg3 must have been. Mark him as moved.
358 if (arg2 == GPRInfo::argumentGPR1)
359 arg2 = arg1;
360 else
361 arg3 = arg1;
362 }
363
364 // Either arg2 & arg3 need swapping, or we're all done.
365 ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
366 || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
367
368 if (arg2 != GPRInfo::argumentGPR2)
369 swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
370 }
371
372 #if CPU(X86_64)
373 ALWAYS_INLINE void setupArguments(FPRReg arg1)
374 {
375 moveDouble(arg1, FPRInfo::argumentFPR0);
376 }
377
378 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
379 {
380 setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
381 }
382 #else
383 ALWAYS_INLINE void setupArguments(FPRReg arg1)
384 {
385 assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
386 }
387
388 ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
389 {
390 assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
391 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
392 }
393 #endif
394
395 ALWAYS_INLINE void setupArguments(GPRReg arg1)
396 {
397 move(arg1, GPRInfo::argumentGPR0);
398 }
399
400 ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
401 {
402 setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
403 }
404
405 ALWAYS_INLINE void setupArgumentsExecState()
406 {
407 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
408 }
409
410 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
411 {
412 move(arg1, GPRInfo::argumentGPR1);
413 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
414 }
415
416 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
417 {
418 move(arg1, GPRInfo::argumentGPR1);
419 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
420 }
421
422 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
423 {
424 setupStubArguments(arg1, arg2);
425 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
426 }
427
428 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
429 {
430 move(arg1, GPRInfo::argumentGPR1);
431 move(arg2, GPRInfo::argumentGPR2);
432 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
433 }
434
435 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, ImmPtr arg2)
436 {
437 move(arg1, GPRInfo::argumentGPR1);
438 move(arg2, GPRInfo::argumentGPR2);
439 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
440 }
441
442 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
443 {
444 move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
445 move(arg1, GPRInfo::argumentGPR1);
446 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
447 }
448
449 ALWAYS_INLINE void setupArgumentsWithExecState(ImmPtr arg1, GPRReg arg2)
450 {
451 move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
452 move(arg1, GPRInfo::argumentGPR1);
453 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
454 }
455
456 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
457 {
458 move(arg1, GPRInfo::argumentGPR1);
459 move(arg2, GPRInfo::argumentGPR2);
460 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
461 }
462
463 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
464 {
465 move(arg1, GPRInfo::argumentGPR1);
466 move(arg2, GPRInfo::argumentGPR2);
467 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
468 }
469
470 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
471 {
472 setupStubArguments(arg1, arg2, arg3);
473 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
474 }
475
476 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
477 {
478 setupStubArguments(arg1, arg2);
479 move(arg3, GPRInfo::argumentGPR3);
480 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
481 }
482
483 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
484 {
485 move(arg1, GPRInfo::argumentGPR1);
486 move(arg2, GPRInfo::argumentGPR2);
487 move(arg3, GPRInfo::argumentGPR3);
488 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
489 }
490
491 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
492 {
493 move(arg1, GPRInfo::argumentGPR1);
494 move(arg2, GPRInfo::argumentGPR2);
495 move(arg3, GPRInfo::argumentGPR3);
496 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
497 }
498
499 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
500 {
501 setupStubArguments(arg1, arg2);
502 move(arg3, GPRInfo::argumentGPR3);
503 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
504 }
505
506 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
507 {
508 move(arg1, GPRInfo::argumentGPR1);
509 move(arg2, GPRInfo::argumentGPR2);
510 move(arg3, GPRInfo::argumentGPR3);
511 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
512 }
513
514 #endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
515 // These methods are suitable for any calling convention that provides for
516 // exactly 4 argument registers, e.g. ARMv7.
517 #if NUMBER_OF_ARGUMENT_REGISTERS == 4
518 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
519 {
520 poke(arg4);
521 setupArgumentsWithExecState(arg1, arg2, arg3);
522 }
523
524 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
525 {
526 poke(arg4);
527 setupArgumentsWithExecState(arg1, arg2, arg3);
528 }
529
530 ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
531 {
532 poke(arg4);
533 setupArgumentsWithExecState(arg1, arg2, arg3);
534 }
535
536 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
537 {
538 poke(arg4);
539 setupArgumentsWithExecState(arg1, arg2, arg3);
540 }
541
542 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
543 {
544 poke(arg5, 1);
545 poke(arg4);
546 setupArgumentsWithExecState(arg1, arg2, arg3);
547 }
548 #endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
549
550 void setupResults(GPRReg destA, GPRReg destB)
551 {
552 GPRReg srcA = GPRInfo::returnValueGPR;
553 GPRReg srcB = GPRInfo::returnValueGPR2;
554
555 if (srcB != destA) {
556 // Handle the easy cases - two simple moves.
557 move(srcA, destA);
558 move(srcB, destB);
559 } else if (srcA != destB) {
560 // Handle the non-swap case - just put srcB in place first.
561 move(srcB, destB);
562 move(srcA, destA);
563 } else
564 swap(destA, destB);
565 }
566 };
567
568 } } // namespace JSC::DFG
569
570 #endif // ENABLE(DFG_JIT)
571
572 #endif // DFGCCallHelpers_h
573