OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Source / JavaScriptCore / dfg / DFGJITCodeGenerator.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 DFGJITCodeGenerator_h
27 #define DFGJITCodeGenerator_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeBlock.h"
32 #include <dfg/DFGGenerationInfo.h>
33 #include <dfg/DFGGraph.h>
34 #include <dfg/DFGJITCompiler.h>
35 #include <dfg/DFGOperations.h>
36 #include <dfg/DFGRegisterBank.h>
37
38 namespace JSC { namespace DFG {
39
40 class SpeculateIntegerOperand;
41 class SpeculateStrictInt32Operand;
42 class SpeculateCellOperand;
43
44
45 // === JITCodeGenerator ===
46 //
47 // This class provides common infrastructure used by the speculative &
48 // non-speculative JITs. Provides common mechanisms for virtual and
49 // physical register management, calls out from JIT code to helper
50 // functions, etc.
51 class JITCodeGenerator {
52 protected:
53     typedef MacroAssembler::TrustedImm32 TrustedImm32;
54     typedef MacroAssembler::Imm32 Imm32;
55
56     // These constants are used to set priorities for spill order for
57     // the register allocator.
58     enum SpillOrder {
59         SpillOrderNone,
60         SpillOrderConstant = 1, // no spill, and cheap fill
61         SpillOrderSpilled = 2,  // no spill
62         SpillOrderJS = 4,       // needs spill
63         SpillOrderCell = 4,     // needs spill
64         SpillOrderInteger = 5,  // needs spill and box
65         SpillOrderDouble = 6,   // needs spill and convert
66         SpillOrderMax
67     };
68
69
70 public:
71     GPRReg fillInteger(NodeIndex, DataFormat& returnFormat);
72     FPRReg fillDouble(NodeIndex);
73     GPRReg fillJSValue(NodeIndex);
74
75     // lock and unlock GPR & FPR registers.
76     void lock(GPRReg reg)
77     {
78         m_gprs.lock(reg);
79     }
80     void lock(FPRReg reg)
81     {
82         m_fprs.lock(reg);
83     }
84     void unlock(GPRReg reg)
85     {
86         m_gprs.unlock(reg);
87     }
88     void unlock(FPRReg reg)
89     {
90         m_fprs.unlock(reg);
91     }
92
93     // Used to check whether a child node is on its last use,
94     // and its machine registers may be reused.
95     bool canReuse(NodeIndex nodeIndex)
96     {
97         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister;
98         GenerationInfo& info = m_generationInfo[virtualRegister];
99         return info.canReuse();
100     }
101     GPRReg reuse(GPRReg reg)
102     {
103         m_gprs.lock(reg);
104         return reg;
105     }
106     FPRReg reuse(FPRReg reg)
107     {
108         m_fprs.lock(reg);
109         return reg;
110     }
111
112     // Allocate a gpr/fpr.
113     GPRReg allocate()
114     {
115         VirtualRegister spillMe;
116         GPRReg gpr = m_gprs.allocate(spillMe);
117         if (spillMe != InvalidVirtualRegister)
118             spill(spillMe);
119         return gpr;
120     }
121     FPRReg fprAllocate()
122     {
123         VirtualRegister spillMe;
124         FPRReg fpr = m_fprs.allocate(spillMe);
125         if (spillMe != InvalidVirtualRegister)
126             spill(spillMe);
127         return fpr;
128     }
129
130     // Check whether a VirtualRegsiter is currently in a machine register.
131     // We use this when filling operands to fill those that are already in
132     // machine registers first (by locking VirtualRegsiters that are already
133     // in machine register before filling those that are not we attempt to
134     // avoid spilling values we will need immediately).
135     bool isFilled(NodeIndex nodeIndex)
136     {
137         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister;
138         GenerationInfo& info = m_generationInfo[virtualRegister];
139         return info.registerFormat() != DataFormatNone;
140     }
141     bool isFilledDouble(NodeIndex nodeIndex)
142     {
143         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister;
144         GenerationInfo& info = m_generationInfo[virtualRegister];
145         return info.registerFormat() == DataFormatDouble;
146     }
147
148 protected:
149     JITCodeGenerator(JITCompiler& jit, bool isSpeculative)
150         : m_jit(jit)
151         , m_isSpeculative(isSpeculative)
152         , m_compileIndex(0)
153         , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
154         , m_blockHeads(jit.graph().m_blocks.size())
155     {
156     }
157
158     // These methods convert between doubles, and doubles boxed and JSValues.
159     GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
160     {
161         JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr);
162         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
163         m_jit.moveDoubleToPtr(fpReg, reg);
164         m_jit.subPtr(JITCompiler::tagTypeNumberRegister, reg);
165         return gpr;
166     }
167     FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
168     {
169         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
170         JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr);
171         m_jit.addPtr(JITCompiler::tagTypeNumberRegister, reg);
172         m_jit.movePtrToDouble(reg, fpReg);
173         return fpr;
174     }
175     GPRReg boxDouble(FPRReg fpr)
176     {
177         return boxDouble(fpr, allocate());
178     }
179     FPRReg unboxDouble(GPRReg gpr)
180     {
181         return unboxDouble(gpr, fprAllocate());
182     }
183
184     // Called on an operand once it has been consumed by a parent node.
185     void use(NodeIndex nodeIndex)
186     {
187         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister;
188         GenerationInfo& info = m_generationInfo[virtualRegister];
189
190         // use() returns true when the value becomes dead, and any
191         // associated resources may be freed.
192         if (!info.use())
193             return;
194
195         // Release the associated machine registers.
196         DataFormat registerFormat = info.registerFormat();
197         if (registerFormat == DataFormatDouble)
198             m_fprs.release(info.fpr());
199         else if (registerFormat != DataFormatNone)
200             m_gprs.release(info.gpr());
201     }
202
203     // Spill a VirtualRegister to the RegisterFile.
204     void spill(VirtualRegister spillMe)
205     {
206         GenerationInfo& info = m_generationInfo[spillMe];
207
208         // Check the GenerationInfo to see if this value need writing
209         // to the RegisterFile - if not, mark it as spilled & return.
210         if (!info.needsSpill()) {
211             info.setSpilled();
212             return;
213         }
214
215         DataFormat spillFormat = info.registerFormat();
216         if (spillFormat == DataFormatDouble) {
217             // All values are spilled as JSValues, so box the double via a temporary gpr.
218             GPRReg gpr = boxDouble(info.fpr());
219             m_jit.storePtr(JITCompiler::gprToRegisterID(gpr), JITCompiler::addressFor(spillMe));
220             unlock(gpr);
221             info.spill(DataFormatJSDouble);
222             return;
223         }
224
225         // The following code handles JSValues, int32s, and cells.
226         ASSERT(spillFormat == DataFormatInteger || spillFormat == DataFormatCell || spillFormat & DataFormatJS);
227
228         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr());
229         // We need to box int32 and cell values ...
230         // but on JSVALUE64 boxing a cell is a no-op!
231         if (spillFormat == DataFormatInteger)
232             m_jit.orPtr(JITCompiler::tagTypeNumberRegister, reg);
233
234         // Spill the value, and record it as spilled in its boxed form.
235         m_jit.storePtr(reg, JITCompiler::addressFor(spillMe));
236         info.spill((DataFormat)(spillFormat | DataFormatJS));
237     }
238
239     // Checks/accessors for constant values.
240     bool isConstant(NodeIndex nodeIndex) { return m_jit.isConstant(nodeIndex); }
241     bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.isInt32Constant(nodeIndex); }
242     bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.isDoubleConstant(nodeIndex); }
243     bool isJSConstant(NodeIndex nodeIndex) { return m_jit.isJSConstant(nodeIndex); }
244     int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); }
245     double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); }
246     JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); }
247
248     Identifier* identifier(unsigned index)
249     {
250         return &m_jit.codeBlock()->identifier(index);
251     }
252
253     // Spill all VirtualRegisters back to the RegisterFile.
254     void flushRegisters()
255     {
256         for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) {
257             VirtualRegister name = m_gprs.name(gpr);
258             if (name != InvalidVirtualRegister) {
259                 spill(name);
260                 m_gprs.release(gpr);
261             }
262         }
263         for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) {
264             VirtualRegister name = m_fprs.name(fpr);
265             if (name != InvalidVirtualRegister) {
266                 spill(name);
267                 m_fprs.release(fpr);
268             }
269         }
270     }
271
272 #ifndef NDEBUG
273     // Used to ASSERT flushRegisters() has been called prior to
274     // calling out from JIT code to a C helper function.
275     bool isFlushed()
276     {
277         for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) {
278             VirtualRegister name = m_gprs.name(gpr);
279             if (name != InvalidVirtualRegister)
280                 return false;
281         }
282         for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) {
283             VirtualRegister name = m_fprs.name(fpr);
284             if (name != InvalidVirtualRegister)
285                 return false;
286         }
287         return true;
288     }
289 #endif
290
291     // Get the JSValue representation of a constant.
292     JSValue constantAsJSValue(NodeIndex nodeIndex)
293     {
294         Node& node = m_jit.graph()[nodeIndex];
295         if (isInt32Constant(nodeIndex))
296             return jsNumber(node.int32Constant());
297         if (isDoubleConstant(nodeIndex))
298             return JSValue(JSValue::EncodeAsDouble, node.numericConstant());
299         ASSERT(isJSConstant(nodeIndex));
300         return valueOfJSConstant(nodeIndex);
301     }
302     MacroAssembler::ImmPtr constantAsJSValueAsImmPtr(NodeIndex nodeIndex)
303     {
304         return MacroAssembler::ImmPtr(JSValue::encode(constantAsJSValue(nodeIndex)));
305     }
306
307     // Helper functions to enable code sharing in implementations of bit/shift ops.
308     void bitOp(NodeType op, int32_t imm, MacroAssembler::RegisterID op1, MacroAssembler::RegisterID result)
309     {
310         switch (op) {
311         case BitAnd:
312             m_jit.and32(Imm32(imm), op1, result);
313             break;
314         case BitOr:
315             m_jit.or32(Imm32(imm), op1, result);
316             break;
317         case BitXor:
318             m_jit.xor32(Imm32(imm), op1, result);
319             break;
320         default:
321             ASSERT_NOT_REACHED();
322         }
323     }
324     void bitOp(NodeType op, MacroAssembler::RegisterID op1, MacroAssembler::RegisterID op2, MacroAssembler::RegisterID result)
325     {
326         switch (op) {
327         case BitAnd:
328             m_jit.and32(op1, op2, result);
329             break;
330         case BitOr:
331             m_jit.or32(op1, op2, result);
332             break;
333         case BitXor:
334             m_jit.xor32(op1, op2, result);
335             break;
336         default:
337             ASSERT_NOT_REACHED();
338         }
339     }
340     void shiftOp(NodeType op, MacroAssembler::RegisterID op1, int32_t shiftAmount, MacroAssembler::RegisterID result)
341     {
342         switch (op) {
343         case BitRShift:
344             m_jit.rshift32(op1, Imm32(shiftAmount), result);
345             break;
346         case BitLShift:
347             m_jit.lshift32(op1, Imm32(shiftAmount), result);
348             break;
349         case BitURShift:
350             m_jit.urshift32(op1, Imm32(shiftAmount), result);
351             break;
352         default:
353             ASSERT_NOT_REACHED();
354         }
355     }
356     void shiftOp(NodeType op, MacroAssembler::RegisterID op1, MacroAssembler::RegisterID shiftAmount, MacroAssembler::RegisterID result)
357     {
358         switch (op) {
359         case BitRShift:
360             m_jit.rshift32(op1, shiftAmount, result);
361             break;
362         case BitLShift:
363             m_jit.lshift32(op1, shiftAmount, result);
364             break;
365         case BitURShift:
366             m_jit.urshift32(op1, shiftAmount, result);
367             break;
368         default:
369             ASSERT_NOT_REACHED();
370         }
371     }
372
373     // Called once a node has completed code generation but prior to setting
374     // its result, to free up its children. (This must happen prior to setting
375     // the nodes result, since the node may have the same VirtualRegister as
376     // a child, and as such will use the same GeneratioInfo).
377     void useChildren(Node&);
378
379     // These method called to initialize the the GenerationInfo
380     // to describe the result of an operation.
381     void integerResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatInteger)
382     {
383         Node& node = m_jit.graph()[nodeIndex];
384         useChildren(node);
385
386         VirtualRegister virtualRegister = node.virtualRegister;
387         GenerationInfo& info = m_generationInfo[virtualRegister];
388
389         if (format == DataFormatInteger) {
390             m_jit.jitAssertIsInt32(reg);
391             m_gprs.retain(reg, virtualRegister, SpillOrderInteger);
392             info.initInteger(nodeIndex, node.refCount, reg);
393         } else {
394             ASSERT(format == DataFormatJSInteger);
395             m_jit.jitAssertIsJSInt32(reg);
396             m_gprs.retain(reg, virtualRegister, SpillOrderJS);
397             info.initJSValue(nodeIndex, node.refCount, reg, format);
398         }
399     }
400     void noResult(NodeIndex nodeIndex)
401     {
402         Node& node = m_jit.graph()[nodeIndex];
403         useChildren(node);
404
405         VirtualRegister virtualRegister = node.virtualRegister;
406         GenerationInfo& info = m_generationInfo[virtualRegister];
407         info.initNone(nodeIndex, node.refCount);
408     }
409     void cellResult(GPRReg reg, NodeIndex nodeIndex)
410     {
411         Node& node = m_jit.graph()[nodeIndex];
412         useChildren(node);
413
414         VirtualRegister virtualRegister = node.virtualRegister;
415         m_gprs.retain(reg, virtualRegister, SpillOrderCell);
416         GenerationInfo& info = m_generationInfo[virtualRegister];
417         info.initCell(nodeIndex, node.refCount, reg);
418     }
419     void jsValueResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatJS)
420     {
421         if (format == DataFormatJSInteger)
422             m_jit.jitAssertIsJSInt32(reg);
423         
424         Node& node = m_jit.graph()[nodeIndex];
425         useChildren(node);
426
427         VirtualRegister virtualRegister = node.virtualRegister;
428         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
429         GenerationInfo& info = m_generationInfo[virtualRegister];
430         info.initJSValue(nodeIndex, node.refCount, reg, format);
431     }
432     void doubleResult(FPRReg reg, NodeIndex nodeIndex)
433     {
434         Node& node = m_jit.graph()[nodeIndex];
435         useChildren(node);
436
437         VirtualRegister virtualRegister = node.virtualRegister;
438         m_fprs.retain(reg, virtualRegister, SpillOrderDouble);
439         GenerationInfo& info = m_generationInfo[virtualRegister];
440         info.initDouble(nodeIndex, node.refCount, reg);
441     }
442     void initConstantInfo(NodeIndex nodeIndex)
443     {
444         ASSERT(isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex) || isJSConstant(nodeIndex));
445         Node& node = m_jit.graph()[nodeIndex];
446         m_generationInfo[node.virtualRegister].initConstant(nodeIndex, node.refCount);
447     }
448
449     // These methods used to sort arguments into the correct registers.
450     template<GPRReg destA, GPRReg destB>
451     void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
452     {
453         // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
454         // (1) both are already in arg regs, the right way around.
455         // (2) both are already in arg regs, the wrong way around.
456         // (3) neither are currently in arg registers.
457         // (4) srcA in in its correct reg.
458         // (5) srcA in in the incorrect reg.
459         // (6) srcB in in its correct reg.
460         // (7) srcB in in the incorrect reg.
461         //
462         // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
463         // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
464         // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
465         // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
466
467         if (srcB != destA) {
468             // Handle the easy cases - two simple moves.
469             m_jit.move(JITCompiler::gprToRegisterID(srcA), JITCompiler::gprToRegisterID(destA));
470             m_jit.move(JITCompiler::gprToRegisterID(srcB), JITCompiler::gprToRegisterID(destB));
471         } else if (srcA != destB) {
472             // Handle the non-swap case - just put srcB in place first.
473             m_jit.move(JITCompiler::gprToRegisterID(srcB), JITCompiler::gprToRegisterID(destB));
474             m_jit.move(JITCompiler::gprToRegisterID(srcA), JITCompiler::gprToRegisterID(destA));
475         } else
476             m_jit.swap(JITCompiler::gprToRegisterID(destB), JITCompiler::gprToRegisterID(destB));
477     }
478     template<FPRReg destA, FPRReg destB>
479     void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
480     {
481         // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
482         // (1) both are already in arg regs, the right way around.
483         // (2) both are already in arg regs, the wrong way around.
484         // (3) neither are currently in arg registers.
485         // (4) srcA in in its correct reg.
486         // (5) srcA in in the incorrect reg.
487         // (6) srcB in in its correct reg.
488         // (7) srcB in in the incorrect reg.
489         //
490         // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
491         // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
492         // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
493         // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
494
495         if (srcB != destA) {
496             // Handle the easy cases - two simple moves.
497             m_jit.moveDouble(JITCompiler::fprToRegisterID(srcA), JITCompiler::fprToRegisterID(destA));
498             m_jit.moveDouble(JITCompiler::fprToRegisterID(srcB), JITCompiler::fprToRegisterID(destB));
499             return;
500         }
501         
502         if (srcA != destB) {
503             // Handle the non-swap case - just put srcB in place first.
504             m_jit.moveDouble(JITCompiler::fprToRegisterID(srcB), JITCompiler::fprToRegisterID(destB));
505             m_jit.moveDouble(JITCompiler::fprToRegisterID(srcA), JITCompiler::fprToRegisterID(destA));
506             return;
507         }
508
509         ASSERT(srcB == destA && srcA == destB);
510         // Need to swap; pick a temporary register.
511         FPRReg temp;
512         if (destA != JITCompiler::argumentFPR3 && destA != JITCompiler::argumentFPR3)
513             temp = JITCompiler::argumentFPR3;
514         else if (destA != JITCompiler::argumentFPR2 && destA != JITCompiler::argumentFPR2)
515             temp = JITCompiler::argumentFPR2;
516         else {
517             ASSERT(destA != JITCompiler::argumentFPR1 && destA != JITCompiler::argumentFPR1);
518             temp = JITCompiler::argumentFPR1;
519         }
520         m_jit.moveDouble(JITCompiler::fprToRegisterID(destA), JITCompiler::fprToRegisterID(temp));
521         m_jit.moveDouble(JITCompiler::fprToRegisterID(destB), JITCompiler::fprToRegisterID(destA));
522         m_jit.moveDouble(JITCompiler::fprToRegisterID(temp), JITCompiler::fprToRegisterID(destB));
523     }
524     void setupStubArguments(GPRReg arg1, GPRReg arg2)
525     {
526         setupTwoStubArgs<JITCompiler::argumentGPR1, JITCompiler::argumentGPR2>(arg1, arg2);
527     }
528     void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
529     {
530         // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
531         // Then we can use setupTwoStubArgs to fix arg2/arg3.
532         if (arg2 != JITCompiler::argumentGPR1 && arg3 != JITCompiler::argumentGPR1) {
533             m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1);
534             setupTwoStubArgs<JITCompiler::argumentGPR2, JITCompiler::argumentGPR3>(arg2, arg3);
535             return;
536         }
537
538         // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
539         // Then we can use setupTwoStubArgs to fix arg1/arg3.
540         if (arg1 != JITCompiler::argumentGPR2 && arg3 != JITCompiler::argumentGPR2) {
541             m_jit.move(JITCompiler::gprToRegisterID(arg2), JITCompiler::argumentRegister2);
542             setupTwoStubArgs<JITCompiler::argumentGPR1, JITCompiler::argumentGPR3>(arg1, arg3);
543             return;
544         }
545
546         // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
547         // Then we can use setupTwoStubArgs to fix arg1/arg2.
548         if (arg1 != JITCompiler::argumentGPR3 && arg2 != JITCompiler::argumentGPR3) {
549             m_jit.move(JITCompiler::gprToRegisterID(arg3), JITCompiler::argumentRegister3);
550             setupTwoStubArgs<JITCompiler::argumentGPR1, JITCompiler::argumentGPR2>(arg1, arg2);
551             return;
552         }
553
554         // If we get here, we haven't been able to move any of arg1/arg2/arg3.
555         // Since all three are blocked, then all three must already be in the argument register.
556         // But are they in the right ones?
557
558         // First, ensure arg1 is in place.
559         if (arg1 != JITCompiler::argumentGPR1) {
560             m_jit.swap(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1);
561
562             // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
563             ASSERT(arg2 == JITCompiler::argumentGPR1 || arg3 == JITCompiler::argumentGPR1);
564             // If arg2 was in argumentGPR1 it no longer is (due to the swap).
565             // Otherwise arg3 must have been. Mark him as moved.
566             if (arg2 == JITCompiler::argumentGPR1)
567                 arg2 = arg1;
568             else
569                 arg3 = arg1;
570         }
571
572         // Either arg2 & arg3 need swapping, or we're all done.
573         ASSERT((arg2 == JITCompiler::argumentGPR2 || arg3 == JITCompiler::argumentGPR3)
574             || (arg2 == JITCompiler::argumentGPR3 || arg3 == JITCompiler::argumentGPR2));
575
576         if (arg2 != JITCompiler::argumentGPR2)
577             m_jit.swap(JITCompiler::argumentRegister2, JITCompiler::argumentRegister3);
578     }
579
580     // These methods add calls to C++ helper functions.
581     void callOperation(J_DFGOperation_EJP operation, GPRReg result, GPRReg arg1, void* pointer)
582     {
583         ASSERT(isFlushed());
584
585         m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1);
586         m_jit.move(JITCompiler::TrustedImmPtr(pointer), JITCompiler::argumentRegister2);
587         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
588
589         appendCallWithExceptionCheck(operation);
590         m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result));
591     }
592     void callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
593     {
594         callOperation((J_DFGOperation_EJP)operation, result, arg1, identifier);
595     }
596     void callOperation(J_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
597     {
598         ASSERT(isFlushed());
599
600         m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1);
601         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
602
603         appendCallWithExceptionCheck(operation);
604         m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result));
605     }
606     void callOperation(Z_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
607     {
608         ASSERT(isFlushed());
609
610         m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1);
611         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
612
613         appendCallWithExceptionCheck(operation);
614         m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result));
615     }
616     void callOperation(Z_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
617     {
618         ASSERT(isFlushed());
619
620         setupStubArguments(arg1, arg2);
621         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
622
623         appendCallWithExceptionCheck(operation);
624         m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result));
625     }
626     void callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
627     {
628         ASSERT(isFlushed());
629
630         setupStubArguments(arg1, arg2);
631         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
632
633         appendCallWithExceptionCheck(operation);
634         m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result));
635     }
636     void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1, GPRReg arg2, void* pointer)
637     {
638         ASSERT(isFlushed());
639
640         setupStubArguments(arg1, arg2);
641         m_jit.move(JITCompiler::TrustedImmPtr(pointer), JITCompiler::argumentRegister3);
642         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
643
644         appendCallWithExceptionCheck(operation);
645     }
646     void callOperation(V_DFGOperation_EJJI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier)
647     {
648         callOperation((V_DFGOperation_EJJP)operation, arg1, arg2, identifier);
649     }
650     void callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
651     {
652         ASSERT(isFlushed());
653
654         setupStubArguments(arg1, arg2, arg3);
655         m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
656
657         appendCallWithExceptionCheck(operation);
658     }
659     void callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
660     {
661         ASSERT(isFlushed());
662
663         setupTwoStubArgs<JITCompiler::argumentFPR0, JITCompiler::argumentFPR1>(arg1, arg2);
664
665         m_jit.appendCall(operation);
666         m_jit.moveDouble(JITCompiler::fpReturnValueRegister, JITCompiler::fprToRegisterID(result));
667     }
668
669     void appendCallWithExceptionCheck(const FunctionPtr& function)
670     {
671         m_jit.appendCallWithExceptionCheck(function, m_jit.graph()[m_compileIndex].exceptionInfo);
672     }
673
674     void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination)
675     {
676         m_branches.append(BranchRecord(jump, destination));
677     }
678
679     void linkBranches()
680     {
681         for (size_t i = 0; i < m_branches.size(); ++i) {
682             BranchRecord& branch = m_branches[i];
683             branch.jump.linkTo(m_blockHeads[branch.destination], &m_jit);
684         }
685     }
686
687 #ifndef NDEBUG
688     void dump(const char* label = 0);
689 #endif
690
691 #if DFG_CONSISTENCY_CHECK
692     void checkConsistency();
693 #else
694     void checkConsistency() {}
695 #endif
696
697     // The JIT, while also provides MacroAssembler functionality.
698     JITCompiler& m_jit;
699     // This flag is used to distinguish speculative and non-speculative
700     // code generation. This is significant when filling spilled values
701     // from the RegisterFile. When spilling we attempt to store information
702     // as to the type of boxed value being stored (int32, double, cell), and
703     // when filling on the speculative path we will retrieve this type info
704     // where available. On the non-speculative path, however, we cannot rely
705     // on the spill format info, since the a value being loaded might have
706     // been spilled by either the speculative or non-speculative paths (where
707     // we entered the non-speculative path on an intervening bail-out), and
708     // the value may have been boxed differently on the two paths.
709     bool m_isSpeculative;
710     // The current node being generated.
711     BlockIndex m_block;
712     NodeIndex m_compileIndex;
713     // Virtual and physical register maps.
714     Vector<GenerationInfo, 32> m_generationInfo;
715     RegisterBank<GPRReg, numberOfGPRs, SpillOrder, SpillOrderNone, SpillOrderMax> m_gprs;
716     RegisterBank<FPRReg, numberOfFPRs, SpillOrder, SpillOrderNone, SpillOrderMax> m_fprs;
717
718     Vector<MacroAssembler::Label> m_blockHeads;
719     struct BranchRecord {
720         BranchRecord(MacroAssembler::Jump jump, BlockIndex destination)
721             : jump(jump)
722             , destination(destination)
723         {
724         }
725
726         MacroAssembler::Jump jump;
727         BlockIndex destination;
728     };
729     Vector<BranchRecord, 8> m_branches;
730 };
731
732 // === Operand types ===
733 //
734 // IntegerOperand, DoubleOperand and JSValueOperand.
735 //
736 // These classes are used to lock the operands to a node into machine
737 // registers. These classes implement of pattern of locking a value
738 // into register at the point of construction only if it is already in
739 // registers, and otherwise loading it lazily at the point it is first
740 // used. We do so in order to attempt to avoid spilling one operand
741 // in order to make space available for another.
742
743 class IntegerOperand {
744 public:
745     explicit IntegerOperand(JITCodeGenerator* jit, NodeIndex index)
746         : m_jit(jit)
747         , m_index(index)
748         , m_gprOrInvalid(InvalidGPRReg)
749 #ifndef NDEBUG
750         , m_format(DataFormatNone)
751 #endif
752     {
753         ASSERT(m_jit);
754         if (jit->isFilled(index))
755             gpr();
756     }
757
758     ~IntegerOperand()
759     {
760         ASSERT(m_gprOrInvalid != InvalidGPRReg);
761         m_jit->unlock(m_gprOrInvalid);
762     }
763
764     NodeIndex index() const
765     {
766         return m_index;
767     }
768
769     GPRReg gpr()
770     {
771         if (m_gprOrInvalid == InvalidGPRReg)
772             m_gprOrInvalid = m_jit->fillInteger(index(), m_format);
773         return m_gprOrInvalid;
774     }
775
776     DataFormat format()
777     {
778         gpr(); // m_format is set when m_gpr is locked.
779         ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
780         return m_format;
781     }
782
783     MacroAssembler::RegisterID registerID()
784     {
785         return JITCompiler::gprToRegisterID(gpr());
786     }
787
788 private:
789     JITCodeGenerator* m_jit;
790     NodeIndex m_index;
791     GPRReg m_gprOrInvalid;
792     DataFormat m_format;
793 };
794
795 class DoubleOperand {
796 public:
797     explicit DoubleOperand(JITCodeGenerator* jit, NodeIndex index)
798         : m_jit(jit)
799         , m_index(index)
800         , m_fprOrInvalid(InvalidFPRReg)
801     {
802         ASSERT(m_jit);
803         if (jit->isFilledDouble(index))
804             fpr();
805     }
806
807     ~DoubleOperand()
808     {
809         ASSERT(m_fprOrInvalid != InvalidFPRReg);
810         m_jit->unlock(m_fprOrInvalid);
811     }
812
813     NodeIndex index() const
814     {
815         return m_index;
816     }
817
818     FPRReg fpr()
819     {
820         if (m_fprOrInvalid == InvalidFPRReg)
821             m_fprOrInvalid = m_jit->fillDouble(index());
822         return m_fprOrInvalid;
823     }
824
825     MacroAssembler::FPRegisterID registerID()
826     {
827         return JITCompiler::fprToRegisterID(fpr());
828     }
829
830 private:
831     JITCodeGenerator* m_jit;
832     NodeIndex m_index;
833     FPRReg m_fprOrInvalid;
834 };
835
836 class JSValueOperand {
837 public:
838     explicit JSValueOperand(JITCodeGenerator* jit, NodeIndex index)
839         : m_jit(jit)
840         , m_index(index)
841         , m_gprOrInvalid(InvalidGPRReg)
842     {
843         ASSERT(m_jit);
844         if (jit->isFilled(index))
845             gpr();
846     }
847
848     ~JSValueOperand()
849     {
850         ASSERT(m_gprOrInvalid != InvalidGPRReg);
851         m_jit->unlock(m_gprOrInvalid);
852     }
853
854     NodeIndex index() const
855     {
856         return m_index;
857     }
858
859     GPRReg gpr()
860     {
861         if (m_gprOrInvalid == InvalidGPRReg)
862             m_gprOrInvalid = m_jit->fillJSValue(index());
863         return m_gprOrInvalid;
864     }
865
866     MacroAssembler::RegisterID registerID()
867     {
868         return JITCompiler::gprToRegisterID(gpr());
869     }
870
871 private:
872     JITCodeGenerator* m_jit;
873     NodeIndex m_index;
874     GPRReg m_gprOrInvalid;
875 };
876
877
878 // === Temporaries ===
879 //
880 // These classes are used to allocate temporary registers.
881 // A mechanism is provided to attempt to reuse the registers
882 // currently allocated to child nodes whose value is consumed
883 // by, and not live after, this operation.
884
885 class GPRTemporary {
886 public:
887     GPRTemporary(JITCodeGenerator*);
888     GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&);
889     GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&, SpeculateIntegerOperand&);
890     GPRTemporary(JITCodeGenerator*, IntegerOperand&);
891     GPRTemporary(JITCodeGenerator*, IntegerOperand&, IntegerOperand&);
892     GPRTemporary(JITCodeGenerator*, SpeculateCellOperand&);
893     GPRTemporary(JITCodeGenerator*, JSValueOperand&);
894
895     ~GPRTemporary()
896     {
897         m_jit->unlock(gpr());
898     }
899
900     GPRReg gpr() const
901     {
902         ASSERT(m_gpr != InvalidGPRReg);
903         return m_gpr;
904     }
905
906     MacroAssembler::RegisterID registerID()
907     {
908         ASSERT(m_gpr != InvalidGPRReg);
909         return JITCompiler::gprToRegisterID(m_gpr);
910     }
911
912 protected:
913     GPRTemporary(JITCodeGenerator* jit, GPRReg lockedGPR)
914         : m_jit(jit)
915         , m_gpr(lockedGPR)
916     {
917     }
918
919 private:
920     JITCodeGenerator* m_jit;
921     GPRReg m_gpr;
922 };
923
924 class FPRTemporary {
925 public:
926     FPRTemporary(JITCodeGenerator*);
927     FPRTemporary(JITCodeGenerator*, DoubleOperand&);
928     FPRTemporary(JITCodeGenerator*, DoubleOperand&, DoubleOperand&);
929
930     ~FPRTemporary()
931     {
932         m_jit->unlock(fpr());
933     }
934
935     FPRReg fpr() const
936     {
937         ASSERT(m_fpr != InvalidFPRReg);
938         return m_fpr;
939     }
940
941     MacroAssembler::FPRegisterID registerID()
942     {
943         ASSERT(m_fpr != InvalidFPRReg);
944         return JITCompiler::fprToRegisterID(m_fpr);
945     }
946
947 protected:
948     FPRTemporary(JITCodeGenerator* jit, FPRReg lockedFPR)
949         : m_jit(jit)
950         , m_fpr(lockedFPR)
951     {
952     }
953
954 private:
955     JITCodeGenerator* m_jit;
956     FPRReg m_fpr;
957 };
958
959
960 // === Results ===
961 //
962 // These classes lock the result of a call to a C++ helper function.
963
964 class GPRResult : public GPRTemporary {
965 public:
966     GPRResult(JITCodeGenerator* jit)
967         : GPRTemporary(jit, lockedResult(jit))
968     {
969     }
970
971 private:
972     static GPRReg lockedResult(JITCodeGenerator* jit)
973     {
974         jit->lock(JITCompiler::returnValueGPR);
975         return JITCompiler::returnValueGPR;
976     }
977 };
978
979 class FPRResult : public FPRTemporary {
980 public:
981     FPRResult(JITCodeGenerator* jit)
982         : FPRTemporary(jit, lockedResult(jit))
983     {
984     }
985
986 private:
987     static FPRReg lockedResult(JITCodeGenerator* jit)
988     {
989         jit->lock(JITCompiler::returnValueFPR);
990         return JITCompiler::returnValueFPR;
991     }
992 };
993
994 } } // namespace JSC::DFG
995
996 #endif
997 #endif
998