b4dfe4d0d93eb1b31a562ceaec58e300da776538
[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/DFGNode.h>
36 #include <dfg/DFGOperations.h>
37 #include <dfg/DFGRegisterBank.h>
38
39 namespace JSC { namespace DFG {
40
41 class SpeculateIntegerOperand;
42 class SpeculateStrictInt32Operand;
43 class SpeculateDoubleOperand;
44 class SpeculateCellOperand;
45 class SpeculateBooleanOperand;
46
47
48 // === JITCodeGenerator ===
49 //
50 // This class provides common infrastructure used by the speculative &
51 // non-speculative JITs. Provides common mechanisms for virtual and
52 // physical register management, calls out from JIT code to helper
53 // functions, etc.
54 class JITCodeGenerator {
55 protected:
56     typedef MacroAssembler::TrustedImm32 TrustedImm32;
57     typedef MacroAssembler::Imm32 Imm32;
58
59     // These constants are used to set priorities for spill order for
60     // the register allocator.
61     enum SpillOrder {
62         SpillOrderConstant = 1, // no spill, and cheap fill
63         SpillOrderSpilled  = 2, // no spill
64         SpillOrderJS       = 4, // needs spill
65         SpillOrderCell     = 4, // needs spill
66         SpillOrderStorage  = 4, // needs spill
67         SpillOrderInteger  = 5, // needs spill and box
68         SpillOrderDouble   = 6, // needs spill and convert
69     };
70     
71     enum UseChildrenMode { CallUseChildren, UseChildrenCalledExplicitly };
72     
73     static const double twoToThe32;
74
75 public:
76     GPRReg fillInteger(NodeIndex, DataFormat& returnFormat);
77     FPRReg fillDouble(NodeIndex);
78 #if USE(JSVALUE64)
79     GPRReg fillJSValue(NodeIndex);
80 #elif USE(JSVALUE32_64)
81     bool fillJSValue(NodeIndex, GPRReg&, GPRReg&, FPRReg&);
82 #endif
83     GPRReg fillStorage(NodeIndex);
84
85     // lock and unlock GPR & FPR registers.
86     void lock(GPRReg reg)
87     {
88         m_gprs.lock(reg);
89     }
90     void lock(FPRReg reg)
91     {
92         m_fprs.lock(reg);
93     }
94     void unlock(GPRReg reg)
95     {
96         m_gprs.unlock(reg);
97     }
98     void unlock(FPRReg reg)
99     {
100         m_fprs.unlock(reg);
101     }
102
103     // Used to check whether a child node is on its last use,
104     // and its machine registers may be reused.
105     bool canReuse(NodeIndex nodeIndex)
106     {
107         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
108         GenerationInfo& info = m_generationInfo[virtualRegister];
109         return info.canReuse();
110     }
111     GPRReg reuse(GPRReg reg)
112     {
113         m_gprs.lock(reg);
114         return reg;
115     }
116     FPRReg reuse(FPRReg reg)
117     {
118         m_fprs.lock(reg);
119         return reg;
120     }
121
122     // Allocate a gpr/fpr.
123     GPRReg allocate()
124     {
125         VirtualRegister spillMe;
126         GPRReg gpr = m_gprs.allocate(spillMe);
127         if (spillMe != InvalidVirtualRegister) {
128 #if USE(JSVALUE32_64)
129             GenerationInfo& info = m_generationInfo[spillMe];
130             ASSERT(info.registerFormat() != DataFormatJSDouble);
131             if ((info.registerFormat() & DataFormatJS))
132                 m_gprs.release(info.tagGPR() == gpr ? info.payloadGPR() : info.tagGPR());
133 #endif
134             spill(spillMe);
135         }
136         return gpr;
137     }
138     GPRReg allocate(GPRReg specific)
139     {
140         VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
141         if (spillMe != InvalidVirtualRegister) {
142 #if USE(JSVALUE32_64)
143             GenerationInfo& info = m_generationInfo[spillMe];
144             ASSERT(info.registerFormat() != DataFormatJSDouble);
145             if ((info.registerFormat() & DataFormatJS))
146                 m_gprs.release(info.tagGPR() == specific ? info.payloadGPR() : info.tagGPR());
147 #endif
148             spill(spillMe);
149         }
150         return specific;
151     }
152     GPRReg tryAllocate()
153     {
154         return m_gprs.tryAllocate();
155     }
156     FPRReg fprAllocate()
157     {
158         VirtualRegister spillMe;
159         FPRReg fpr = m_fprs.allocate(spillMe);
160         if (spillMe != InvalidVirtualRegister)
161             spill(spillMe);
162         return fpr;
163     }
164
165     // Check whether a VirtualRegsiter is currently in a machine register.
166     // We use this when filling operands to fill those that are already in
167     // machine registers first (by locking VirtualRegsiters that are already
168     // in machine register before filling those that are not we attempt to
169     // avoid spilling values we will need immediately).
170     bool isFilled(NodeIndex nodeIndex)
171     {
172         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
173         GenerationInfo& info = m_generationInfo[virtualRegister];
174         return info.registerFormat() != DataFormatNone;
175     }
176     bool isFilledDouble(NodeIndex nodeIndex)
177     {
178         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
179         GenerationInfo& info = m_generationInfo[virtualRegister];
180         return info.registerFormat() == DataFormatDouble;
181     }
182
183     // Called on an operand once it has been consumed by a parent node.
184     void use(NodeIndex nodeIndex)
185     {
186         VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
187         GenerationInfo& info = m_generationInfo[virtualRegister];
188
189         // use() returns true when the value becomes dead, and any
190         // associated resources may be freed.
191         if (!info.use())
192             return;
193
194         // Release the associated machine registers.
195         DataFormat registerFormat = info.registerFormat();
196 #if USE(JSVALUE64)
197         if (registerFormat == DataFormatDouble)
198             m_fprs.release(info.fpr());
199         else if (registerFormat != DataFormatNone)
200             m_gprs.release(info.gpr());
201 #elif USE(JSVALUE32_64)
202         if (registerFormat == DataFormatDouble || registerFormat == DataFormatJSDouble)
203             m_fprs.release(info.fpr());
204         else if (registerFormat == DataFormatInteger || registerFormat == DataFormatCell || registerFormat == DataFormatStorage)
205             m_gprs.release(info.gpr());
206         else if (registerFormat & DataFormatJS) {
207             m_gprs.release(info.tagGPR());
208             m_gprs.release(info.payloadGPR());
209         }
210 #endif
211     }
212
213     static void markCellCard(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2);
214     static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind);
215
216     void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
217     void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg);
218
219     static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg)
220     {
221         if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0)
222             return GPRInfo::regT0;
223
224         if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1)
225             return GPRInfo::regT1;
226
227         if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2)
228             return GPRInfo::regT2;
229
230         return GPRInfo::regT3;
231     }
232
233 protected:
234     JITCodeGenerator(JITCompiler& jit, bool isSpeculative)
235         : m_jit(jit)
236         , m_isSpeculative(isSpeculative)
237         , m_compileIndex(0)
238         , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
239         , m_blockHeads(jit.graph().m_blocks.size())
240     {
241     }
242     
243     void clearGenerationInfo();
244
245 #if USE(JSVALUE32_64)
246     bool registersMatched(GenerationInfo& info, GPRReg exclude, GPRReg exclude2)
247     {
248         ASSERT(info.registerFormat() != DataFormatNone);
249         ASSERT(info.registerFormat() != DataFormatDouble);
250         ASSERT(info.registerFormat() != DataFormatJSDouble);
251         return !(info.registerFormat() & DataFormatJS) ? (info.gpr() == exclude || info.gpr() == exclude2) :  (info.tagGPR() == exclude || info.tagGPR() == exclude2 || info.payloadGPR() == exclude || info.payloadGPR() == exclude2);
252     }
253 #endif
254
255     // These methods are used when generating 'unexpected'
256     // calls out from JIT code to C++ helper routines -
257     // they spill all live values to the appropriate
258     // slots in the RegisterFile without changing any state
259     // in the GenerationInfo.
260     void silentSpillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg, GPRReg exclude2 = InvalidGPRReg)
261     {
262         GenerationInfo& info = m_generationInfo[spillMe];
263         ASSERT(info.registerFormat() != DataFormatNone);
264         ASSERT(info.registerFormat() != DataFormatDouble);
265
266 #if USE(JSVALUE64)
267         UNUSED_PARAM(exclude2);
268         if (!info.needsSpill() || (info.gpr() == exclude))
269 #elif USE(JSVALUE32_64)
270         if (!info.needsSpill() || registersMatched(info, exclude, exclude2))
271 #endif
272             return;
273
274         DataFormat registerFormat = info.registerFormat();
275
276 #if USE(JSVALUE64)
277         if (registerFormat == DataFormatInteger)
278             m_jit.store32(info.gpr(), JITCompiler::addressFor(spillMe));
279         else {
280             ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell || registerFormat == DataFormatStorage);
281             m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
282         }
283 #elif USE(JSVALUE32_64)
284         if (registerFormat == DataFormatInteger)
285             m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
286         else if (registerFormat == DataFormatCell)
287             m_jit.storePtr(info.gpr(), JITCompiler::payloadFor(spillMe));
288         else if (registerFormat == DataFormatStorage)
289             m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
290         else {
291             ASSERT(registerFormat & DataFormatJS);
292             m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
293             m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
294         }
295 #endif
296     }
297     void silentSpillFPR(VirtualRegister spillMe, FPRReg exclude = InvalidFPRReg)
298     {
299         GenerationInfo& info = m_generationInfo[spillMe];
300         ASSERT(info.registerFormat() == DataFormatDouble);
301
302         if (info.fpr() == exclude)
303             return;
304         if (!info.needsSpill()) {
305             // it's either a constant or it's already been spilled
306             ASSERT(m_jit.graph()[info.nodeIndex()].hasConstant() || info.spillFormat() != DataFormatNone);
307             return;
308         }
309         
310         // it's neither a constant nor has it been spilled.
311         ASSERT(!m_jit.graph()[info.nodeIndex()].hasConstant());
312         ASSERT(info.spillFormat() == DataFormatNone);
313
314         m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
315     }
316
317     void silentFillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg, GPRReg exclude2 = InvalidGPRReg)
318     {
319         GenerationInfo& info = m_generationInfo[spillMe];
320 #if USE(JSVALUE64)
321         UNUSED_PARAM(exclude2);
322         if (info.gpr() == exclude)
323 #elif USE(JSVALUE32_64)
324         if (registersMatched(info, exclude, exclude2))
325 #endif
326             return;
327
328         NodeIndex nodeIndex = info.nodeIndex();
329         Node& node = m_jit.graph()[nodeIndex];
330         ASSERT(info.registerFormat() != DataFormatNone);
331         ASSERT(info.registerFormat() != DataFormatDouble);
332         DataFormat registerFormat = info.registerFormat();
333
334 #if USE(JSVALUE64)
335         if (registerFormat == DataFormatInteger) {
336             if (node.hasConstant()) {
337                 ASSERT(isInt32Constant(nodeIndex));
338                 m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());
339             } else
340                 m_jit.load32(JITCompiler::addressFor(spillMe), info.gpr());
341             return;
342         }
343
344         if (node.hasConstant())
345             m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), info.gpr());
346         else {
347             ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell || registerFormat == DataFormatStorage);
348             m_jit.loadPtr(JITCompiler::addressFor(spillMe), info.gpr());
349         }
350 #elif USE(JSVALUE32_64)
351         if (registerFormat == DataFormatInteger || registerFormat == DataFormatCell) {
352             if (node.isConstant())
353                 m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());
354             else
355                 m_jit.load32(JITCompiler::payloadFor(spillMe), info.gpr());
356         } else if (registerFormat == DataFormatStorage)
357             m_jit.load32(JITCompiler::addressFor(spillMe), info.gpr());
358         else 
359             m_jit.emitLoad(nodeIndex, info.tagGPR(), info.payloadGPR());
360 #endif
361     }
362
363     void silentFillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg exclude = InvalidFPRReg)
364     {
365         GenerationInfo& info = m_generationInfo[spillMe];
366         if (info.fpr() == exclude)
367             return;
368
369         NodeIndex nodeIndex = info.nodeIndex();
370 #if USE(JSVALUE64)
371         Node& node = m_jit.graph()[nodeIndex];
372         ASSERT(info.registerFormat() == DataFormatDouble);
373
374         if (node.hasConstant()) {
375             ASSERT(isNumberConstant(nodeIndex));
376             m_jit.move(JITCompiler::ImmPtr(bitwise_cast<void*>(valueOfNumberConstant(nodeIndex))), canTrample);
377             m_jit.movePtrToDouble(canTrample, info.fpr());
378             return;
379         }
380         
381         if (info.spillFormat() != DataFormatNone) {
382             // it was already spilled previously, which means we need unboxing.
383             ASSERT(info.spillFormat() & DataFormatJS);
384             m_jit.loadPtr(JITCompiler::addressFor(spillMe), canTrample);
385             unboxDouble(canTrample, info.fpr());
386             return;
387         }
388
389         m_jit.loadDouble(JITCompiler::addressFor(spillMe), info.fpr());
390 #elif USE(JSVALUE32_64)
391         UNUSED_PARAM(canTrample);
392         ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble);
393         m_jit.emitLoadDouble(nodeIndex, info.fpr());
394 #endif
395     }
396
397     void silentSpillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg)
398     {
399         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
400             if (iter.name() != InvalidVirtualRegister)
401                 silentSpillGPR(iter.name(), exclude, exclude2);
402         }
403         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
404             if (iter.name() != InvalidVirtualRegister)
405                 silentSpillFPR(iter.name());
406         }
407     }
408     void silentSpillAllRegisters(FPRReg exclude)
409     {
410         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
411             if (iter.name() != InvalidVirtualRegister)
412                 silentSpillGPR(iter.name());
413         }
414         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
415             if (iter.name() != InvalidVirtualRegister)
416                 silentSpillFPR(iter.name(), exclude);
417         }
418     }
419
420     void silentFillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg)
421     {
422         GPRReg canTrample = GPRInfo::regT0;
423         if (exclude == GPRInfo::regT0)
424             canTrample = GPRInfo::regT1;
425         
426         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
427             if (iter.name() != InvalidVirtualRegister)
428                 silentFillFPR(iter.name(), canTrample);
429         }
430         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
431             if (iter.name() != InvalidVirtualRegister)
432                 silentFillGPR(iter.name(), exclude, exclude2);
433         }
434     }
435     void silentFillAllRegisters(FPRReg exclude)
436     {
437         GPRReg canTrample = GPRInfo::regT0;
438         
439         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
440             if (iter.name() != InvalidVirtualRegister) {
441                 ASSERT_UNUSED(exclude, iter.regID() != exclude);
442                 silentFillFPR(iter.name(), canTrample, exclude);
443             }
444         }
445         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
446             if (iter.name() != InvalidVirtualRegister)
447                 silentFillGPR(iter.name());
448         }
449     }
450
451     // These methods convert between doubles, and doubles boxed and JSValues.
452 #if USE(JSVALUE64)
453     GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
454     {
455         return m_jit.boxDouble(fpr, gpr);
456     }
457     FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
458     {
459         return m_jit.unboxDouble(gpr, fpr);
460     }
461     GPRReg boxDouble(FPRReg fpr)
462     {
463         return boxDouble(fpr, allocate());
464     }
465 #elif USE(JSVALUE32_64)
466     void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR, VirtualRegister virtualRegister)
467     {
468         m_jit.boxDouble(fpr, tagGPR, payloadGPR, virtualRegister);
469     }
470     void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, VirtualRegister virtualRegister)
471     {
472         m_jit.unboxDouble(tagGPR, payloadGPR, fpr, virtualRegister);
473     }
474 #endif
475
476     // Spill a VirtualRegister to the RegisterFile.
477     void spill(VirtualRegister spillMe)
478     {
479         GenerationInfo& info = m_generationInfo[spillMe];
480
481 #if USE(JSVALUE32_64)
482         if (info.registerFormat() == DataFormatNone) // it has been spilled. JS values which have two GPRs can reach here
483             return;
484 #endif
485         // Check the GenerationInfo to see if this value need writing
486         // to the RegisterFile - if not, mark it as spilled & return.
487         if (!info.needsSpill()) {
488             info.setSpilled();
489             return;
490         }
491
492         DataFormat spillFormat = info.registerFormat();
493         switch (spillFormat) {
494         case DataFormatStorage: {
495             // This is special, since it's not a JS value - as in it's not visible to JS
496             // code.
497             m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
498             info.spill(DataFormatStorage);
499             return;
500         }
501
502 #if USE(JSVALUE64)
503         case DataFormatDouble: {
504             // All values are spilled as JSValues, so box the double via a temporary gpr.
505             GPRReg gpr = boxDouble(info.fpr());
506             m_jit.storePtr(gpr, JITCompiler::addressFor(spillMe));
507             unlock(gpr);
508             info.spill(DataFormatJSDouble);
509             return;
510         }
511
512         default:
513             // The following code handles JSValues, int32s, and cells.
514             ASSERT(spillFormat == DataFormatInteger || spillFormat == DataFormatCell || spillFormat & DataFormatJS);
515             
516             GPRReg reg = info.gpr();
517             // We need to box int32 and cell values ...
518             // but on JSVALUE64 boxing a cell is a no-op!
519             if (spillFormat == DataFormatInteger)
520                 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, reg);
521             
522             // Spill the value, and record it as spilled in its boxed form.
523             m_jit.storePtr(reg, JITCompiler::addressFor(spillMe));
524             info.spill((DataFormat)(spillFormat | DataFormatJS));
525             return;
526         }
527 #elif USE(JSVALUE32_64)
528         case DataFormatDouble:
529         case DataFormatJSDouble: {
530             // On JSVALUE32_64 boxing a double is a no-op.
531             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
532             info.spill(DataFormatJSDouble);
533             return;
534         }
535         default:
536             // The following code handles JSValues, int32s, and cells.
537             ASSERT(spillFormat == DataFormatInteger || spillFormat == DataFormatCell || spillFormat & DataFormatJS);
538
539             if (spillFormat == DataFormatInteger || spillFormat == DataFormatCell) {
540                 GPRReg reg = info.gpr();
541                 m_jit.store32(reg, JITCompiler::payloadFor(spillMe));
542                 // We need to box int32 and cell values ...
543                 if (spillFormat == DataFormatInteger)
544                     m_jit.store32(TrustedImm32(JSValue::Int32Tag), JITCompiler::tagFor(spillMe));
545                 else // cells
546                     m_jit.store32(TrustedImm32(JSValue::CellTag), JITCompiler::tagFor(spillMe));
547             } else { // JSValue
548                 m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
549                 m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
550             }
551             info.spill((DataFormat)(spillFormat | DataFormatJS));
552             return;
553         }
554 #endif
555     }
556     
557     bool isStrictInt32(NodeIndex);
558     
559     bool isKnownInteger(NodeIndex);
560     bool isKnownNumeric(NodeIndex);
561     bool isKnownCell(NodeIndex);
562     
563     bool isKnownNotInteger(NodeIndex);
564     bool isKnownNotNumber(NodeIndex);
565
566     bool isKnownBoolean(NodeIndex);
567
568     bool isKnownNotCell(NodeIndex);
569     
570     // Checks/accessors for constant values.
571     bool isConstant(NodeIndex nodeIndex) { return m_jit.isConstant(nodeIndex); }
572     bool isJSConstant(NodeIndex nodeIndex) { return m_jit.isJSConstant(nodeIndex); }
573     bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.isInt32Constant(nodeIndex); }
574     bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.isDoubleConstant(nodeIndex); }
575     bool isNumberConstant(NodeIndex nodeIndex) { return m_jit.isNumberConstant(nodeIndex); }
576     bool isBooleanConstant(NodeIndex nodeIndex) { return m_jit.isBooleanConstant(nodeIndex); }
577     bool isFunctionConstant(NodeIndex nodeIndex) { return m_jit.isFunctionConstant(nodeIndex); }
578     int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); }
579     double valueOfNumberConstant(NodeIndex nodeIndex) { return m_jit.valueOfNumberConstant(nodeIndex); }
580 #if USE(JSVALUE32_64)
581     void* addressOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.addressOfDoubleConstant(nodeIndex); }
582 #endif
583     JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); }
584     bool valueOfBooleanConstant(NodeIndex nodeIndex) { return m_jit.valueOfBooleanConstant(nodeIndex); }
585     JSFunction* valueOfFunctionConstant(NodeIndex nodeIndex) { return m_jit.valueOfFunctionConstant(nodeIndex); }
586     bool isNullConstant(NodeIndex nodeIndex)
587     {
588         if (!isConstant(nodeIndex))
589             return false;
590         return valueOfJSConstant(nodeIndex).isNull();
591     }
592
593     Identifier* identifier(unsigned index)
594     {
595         return &m_jit.codeBlock()->identifier(index);
596     }
597
598     // Spill all VirtualRegisters back to the RegisterFile.
599     void flushRegisters()
600     {
601         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
602             if (iter.name() != InvalidVirtualRegister) {
603                 spill(iter.name());
604                 iter.release();
605             }
606         }
607         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
608             if (iter.name() != InvalidVirtualRegister) {
609                 spill(iter.name());
610                 iter.release();
611             }
612         }
613     }
614
615 #ifndef NDEBUG
616     // Used to ASSERT flushRegisters() has been called prior to
617     // calling out from JIT code to a C helper function.
618     bool isFlushed()
619     {
620         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
621             if (iter.name() != InvalidVirtualRegister)
622                 return false;
623         }
624         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
625             if (iter.name() != InvalidVirtualRegister)
626                 return false;
627         }
628         return true;
629     }
630 #endif
631
632 #if USE(JSVALUE64)
633     MacroAssembler::ImmPtr valueOfJSConstantAsImmPtr(NodeIndex nodeIndex)
634     {
635         return MacroAssembler::ImmPtr(JSValue::encode(valueOfJSConstant(nodeIndex)));
636     }
637 #endif
638
639     // Helper functions to enable code sharing in implementations of bit/shift ops.
640     void bitOp(NodeType op, int32_t imm, GPRReg op1, GPRReg result)
641     {
642         switch (op) {
643         case BitAnd:
644             m_jit.and32(Imm32(imm), op1, result);
645             break;
646         case BitOr:
647             m_jit.or32(Imm32(imm), op1, result);
648             break;
649         case BitXor:
650             m_jit.xor32(Imm32(imm), op1, result);
651             break;
652         default:
653             ASSERT_NOT_REACHED();
654         }
655     }
656     void bitOp(NodeType op, GPRReg op1, GPRReg op2, GPRReg result)
657     {
658         switch (op) {
659         case BitAnd:
660             m_jit.and32(op1, op2, result);
661             break;
662         case BitOr:
663             m_jit.or32(op1, op2, result);
664             break;
665         case BitXor:
666             m_jit.xor32(op1, op2, result);
667             break;
668         default:
669             ASSERT_NOT_REACHED();
670         }
671     }
672     void shiftOp(NodeType op, GPRReg op1, int32_t shiftAmount, GPRReg result)
673     {
674         switch (op) {
675         case BitRShift:
676             m_jit.rshift32(op1, Imm32(shiftAmount), result);
677             break;
678         case BitLShift:
679             m_jit.lshift32(op1, Imm32(shiftAmount), result);
680             break;
681         case BitURShift:
682             m_jit.urshift32(op1, Imm32(shiftAmount), result);
683             break;
684         default:
685             ASSERT_NOT_REACHED();
686         }
687     }
688     void shiftOp(NodeType op, GPRReg op1, GPRReg shiftAmount, GPRReg result)
689     {
690         switch (op) {
691         case BitRShift:
692             m_jit.rshift32(op1, shiftAmount, result);
693             break;
694         case BitLShift:
695             m_jit.lshift32(op1, shiftAmount, result);
696             break;
697         case BitURShift:
698             m_jit.urshift32(op1, shiftAmount, result);
699             break;
700         default:
701             ASSERT_NOT_REACHED();
702         }
703     }
704     
705     // Returns the node index of the branch node if peephole is okay, NoNode otherwise.
706     NodeIndex detectPeepHoleBranch()
707     {
708         NodeIndex lastNodeIndex = m_jit.graph().m_blocks[m_block]->end - 1;
709
710         // Check that no intervening nodes will be generated.
711         for (NodeIndex index = m_compileIndex + 1; index < lastNodeIndex; ++index) {
712             if (m_jit.graph()[index].shouldGenerate())
713                 return NoNode;
714         }
715
716         // Check if the lastNode is a branch on this node.
717         Node& lastNode = m_jit.graph()[lastNodeIndex];
718         return lastNode.op == Branch && lastNode.child1() == m_compileIndex ? lastNodeIndex : NoNode;
719     }
720     
721     void nonSpeculativeValueToNumber(Node&);
722     void nonSpeculativeValueToInt32(Node&);
723     void nonSpeculativeUInt32ToNumber(Node&);
724
725     void nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute);
726     void nonSpeculativeBasicArithOp(NodeType op, Node&);
727     
728     // Handles both ValueAdd and ArithAdd.
729     void nonSpeculativeAdd(NodeType op, Node& node)
730     {
731         if (isInt32Constant(node.child1())) {
732             nonSpeculativeKnownConstantArithOp(op, node.child2(), node.child1(), true);
733             return;
734         }
735         
736         if (isInt32Constant(node.child2())) {
737             nonSpeculativeKnownConstantArithOp(op, node.child1(), node.child2(), false);
738             return;
739         }
740         
741         nonSpeculativeBasicArithOp(op, node);
742     }
743     
744     void nonSpeculativeArithSub(Node& node)
745     {
746         if (isInt32Constant(node.child2())) {
747             nonSpeculativeKnownConstantArithOp(ArithSub, node.child1(), node.child2(), false);
748             return;
749         }
750         
751         nonSpeculativeBasicArithOp(ArithSub, node);
752     }
753     
754     void nonSpeculativeArithMod(Node&);
755     void nonSpeculativeCheckHasInstance(Node&);
756     void nonSpeculativeInstanceOf(Node&);
757
758 #if USE(JSVALUE64)
759     JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), NodeType = GetById);
760     void cachedPutById(GPRReg base, GPRReg value, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
761     void cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
762 #elif USE(JSVALUE32_64)
763     JITCompiler::Call cachedGetById(GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), NodeType = GetById);
764     void cachedPutById(GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
765     void cachedGetMethod(GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
766 #endif
767
768     void nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert = false);
769     void nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert = false);
770     bool nonSpeculativeCompareNull(Node&, NodeIndex operand, bool invert = false);
771     
772     void nonSpeculativePeepholeBranch(Node&, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
773     void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
774     bool nonSpeculativeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
775     
776     void nonSpeculativePeepholeStrictEq(Node&, NodeIndex branchNodeIndex, bool invert = false);
777     void nonSpeculativeNonPeepholeStrictEq(Node&, bool invert = false);
778     bool nonSpeculativeStrictEq(Node&, bool invert = false);
779     
780     void emitBranch(Node&);
781     
782     void nonSpeculativeLogicalNot(Node&);
783     
784     MacroAssembler::Address addressOfCallData(int idx)
785     {
786         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + idx) * static_cast<int>(sizeof(Register)));
787     }
788     
789     void emitCall(Node&);
790     
791     void speculationCheck(MacroAssembler::Jump jumpToFail);
792
793     // Called once a node has completed code generation but prior to setting
794     // its result, to free up its children. (This must happen prior to setting
795     // the nodes result, since the node may have the same VirtualRegister as
796     // a child, and as such will use the same GeneratioInfo).
797     void useChildren(Node&);
798
799     // These method called to initialize the the GenerationInfo
800     // to describe the result of an operation.
801     void integerResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatInteger, UseChildrenMode mode = CallUseChildren)
802     {
803         Node& node = m_jit.graph()[nodeIndex];
804         if (mode == CallUseChildren)
805             useChildren(node);
806
807         VirtualRegister virtualRegister = node.virtualRegister();
808         GenerationInfo& info = m_generationInfo[virtualRegister];
809
810         if (format == DataFormatInteger) {
811             m_jit.jitAssertIsInt32(reg);
812             m_gprs.retain(reg, virtualRegister, SpillOrderInteger);
813             info.initInteger(nodeIndex, node.refCount(), reg);
814         } else {
815 #if USE(JSVALUE64)
816             ASSERT(format == DataFormatJSInteger);
817             m_jit.jitAssertIsJSInt32(reg);
818             m_gprs.retain(reg, virtualRegister, SpillOrderJS);
819             info.initJSValue(nodeIndex, node.refCount(), reg, format);
820 #elif USE(JSVALUE32_64)
821             ASSERT_NOT_REACHED();
822 #endif
823         }
824     }
825     void integerResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode)
826     {
827         integerResult(reg, nodeIndex, DataFormatInteger, mode);
828     }
829     void noResult(NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
830     {
831         if (mode == UseChildrenCalledExplicitly)
832             return;
833         Node& node = m_jit.graph()[nodeIndex];
834         useChildren(node);
835     }
836     void cellResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
837     {
838         Node& node = m_jit.graph()[nodeIndex];
839         if (mode == CallUseChildren)
840             useChildren(node);
841
842         VirtualRegister virtualRegister = node.virtualRegister();
843         m_gprs.retain(reg, virtualRegister, SpillOrderCell);
844         GenerationInfo& info = m_generationInfo[virtualRegister];
845         info.initCell(nodeIndex, node.refCount(), reg);
846     }
847 #if USE(JSVALUE64)
848     void jsValueResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
849     {
850         if (format == DataFormatJSInteger)
851             m_jit.jitAssertIsJSInt32(reg);
852         
853         Node& node = m_jit.graph()[nodeIndex];
854         if (mode == CallUseChildren)
855             useChildren(node);
856
857         VirtualRegister virtualRegister = node.virtualRegister();
858         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
859         GenerationInfo& info = m_generationInfo[virtualRegister];
860         info.initJSValue(nodeIndex, node.refCount(), reg, format);
861     }
862     void jsValueResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode)
863     {
864         jsValueResult(reg, nodeIndex, DataFormatJS, mode);
865     }
866 #elif USE(JSVALUE32_64)
867     void jsValueResult(GPRReg tag, GPRReg payload, NodeIndex nodeIndex, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
868     {
869         Node& node = m_jit.graph()[nodeIndex];
870         if (mode == CallUseChildren)
871             useChildren(node);
872
873         VirtualRegister virtualRegister = node.virtualRegister();
874         m_gprs.retain(tag, virtualRegister, SpillOrderJS);
875         m_gprs.retain(payload, virtualRegister, SpillOrderJS);
876         GenerationInfo& info = m_generationInfo[virtualRegister];
877         info.initJSValue(nodeIndex, node.refCount(), tag, payload, format);
878     }
879     void jsValueResult(GPRReg tag, GPRReg payload, NodeIndex nodeIndex, UseChildrenMode mode)
880     {
881         jsValueResult(tag, payload, nodeIndex, DataFormatJS, mode);
882     }
883 #endif
884     void storageResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
885     {
886         Node& node = m_jit.graph()[nodeIndex];
887         if (mode == CallUseChildren)
888             useChildren(node);
889         
890         VirtualRegister virtualRegister = node.virtualRegister();
891         m_gprs.retain(reg, virtualRegister, SpillOrderStorage);
892         GenerationInfo& info = m_generationInfo[virtualRegister];
893         info.initStorage(nodeIndex, node.refCount(), reg);
894     }
895     void doubleResult(FPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
896     {
897         Node& node = m_jit.graph()[nodeIndex];
898         if (mode == CallUseChildren)
899             useChildren(node);
900
901         VirtualRegister virtualRegister = node.virtualRegister();
902         m_fprs.retain(reg, virtualRegister, SpillOrderDouble);
903         GenerationInfo& info = m_generationInfo[virtualRegister];
904         info.initDouble(nodeIndex, node.refCount(), reg);
905     }
906     void initConstantInfo(NodeIndex nodeIndex)
907     {
908         ASSERT(isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex) || isJSConstant(nodeIndex));
909         Node& node = m_jit.graph()[nodeIndex];
910         m_generationInfo[node.virtualRegister()].initConstant(nodeIndex, node.refCount());
911     }
912
913     // These methods used to sort arguments into the correct registers.
914     template<GPRReg destA, GPRReg destB>
915     void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
916     {
917         // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
918         // (1) both are already in arg regs, the right way around.
919         // (2) both are already in arg regs, the wrong way around.
920         // (3) neither are currently in arg registers.
921         // (4) srcA in in its correct reg.
922         // (5) srcA in in the incorrect reg.
923         // (6) srcB in in its correct reg.
924         // (7) srcB in in the incorrect reg.
925         //
926         // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
927         // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
928         // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
929         // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
930
931         if (srcB != destA) {
932             // Handle the easy cases - two simple moves.
933             m_jit.move(srcA, destA);
934             m_jit.move(srcB, destB);
935         } else if (srcA != destB) {
936             // Handle the non-swap case - just put srcB in place first.
937             m_jit.move(srcB, destB);
938             m_jit.move(srcA, destA);
939         } else
940             m_jit.swap(destA, destB);
941     }
942 #if CPU(X86_64)
943     template<FPRReg destA, FPRReg destB>
944     void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
945     {
946         // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
947         // (1) both are already in arg regs, the right way around.
948         // (2) both are already in arg regs, the wrong way around.
949         // (3) neither are currently in arg registers.
950         // (4) srcA in in its correct reg.
951         // (5) srcA in in the incorrect reg.
952         // (6) srcB in in its correct reg.
953         // (7) srcB in in the incorrect reg.
954         //
955         // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
956         // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
957         // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
958         // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
959
960         if (srcB != destA) {
961             // Handle the easy cases - two simple moves.
962             m_jit.moveDouble(srcA, destA);
963             m_jit.moveDouble(srcB, destB);
964             return;
965         }
966         
967         if (srcA != destB) {
968             // Handle the non-swap case - just put srcB in place first.
969             m_jit.moveDouble(srcB, destB);
970             m_jit.moveDouble(srcA, destA);
971             return;
972         }
973
974         ASSERT(srcB == destA && srcA == destB);
975         // Need to swap; pick a temporary register.
976         FPRReg temp;
977         if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
978             temp = FPRInfo::argumentFPR3;
979         else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
980             temp = FPRInfo::argumentFPR2;
981         else {
982             ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
983             temp = FPRInfo::argumentFPR1;
984         }
985         m_jit.moveDouble(destA, temp);
986         m_jit.moveDouble(destB, destA);
987         m_jit.moveDouble(temp, destB);
988     }
989     void setupStubArguments(GPRReg arg1, GPRReg arg2)
990     {
991         setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
992     }
993     void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
994     {
995         // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
996         // Then we can use setupTwoStubArgs to fix arg2/arg3.
997         if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
998             m_jit.move(arg1, GPRInfo::argumentGPR1);
999             setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
1000             return;
1001         }
1002
1003         // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
1004         // Then we can use setupTwoStubArgs to fix arg1/arg3.
1005         if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
1006             m_jit.move(arg2, GPRInfo::argumentGPR2);
1007             setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
1008             return;
1009         }
1010
1011         // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
1012         // Then we can use setupTwoStubArgs to fix arg1/arg2.
1013         if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
1014             m_jit.move(arg3, GPRInfo::argumentGPR3);
1015             setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
1016             return;
1017         }
1018
1019         // If we get here, we haven't been able to move any of arg1/arg2/arg3.
1020         // Since all three are blocked, then all three must already be in the argument register.
1021         // But are they in the right ones?
1022
1023         // First, ensure arg1 is in place.
1024         if (arg1 != GPRInfo::argumentGPR1) {
1025             m_jit.swap(arg1, GPRInfo::argumentGPR1);
1026
1027             // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
1028             ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
1029             // If arg2 was in argumentGPR1 it no longer is (due to the swap).
1030             // Otherwise arg3 must have been. Mark him as moved.
1031             if (arg2 == GPRInfo::argumentGPR1)
1032                 arg2 = arg1;
1033             else
1034                 arg3 = arg1;
1035         }
1036
1037         // Either arg2 & arg3 need swapping, or we're all done.
1038         ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
1039             || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
1040
1041         if (arg2 != GPRInfo::argumentGPR2)
1042             m_jit.swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
1043     }
1044
1045     // These methods add calls to C++ helper functions.
1046     void callOperation(J_DFGOperation_EP operation, GPRReg result, void* pointer)
1047     {
1048         ASSERT(isFlushed());
1049
1050         m_jit.move(JITCompiler::TrustedImmPtr(pointer), GPRInfo::argumentGPR1);
1051         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1052
1053         appendCallWithExceptionCheck(operation);
1054         m_jit.move(GPRInfo::returnValueGPR, result);
1055     }
1056     void callOperation(J_DFGOperation_EI operation, GPRReg result, Identifier* identifier)
1057     {
1058         callOperation((J_DFGOperation_EP)operation, result, identifier);
1059     }
1060     void callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
1061     {
1062         ASSERT(isFlushed());
1063
1064         m_jit.move(JITCompiler::TrustedImmPtr(size), GPRInfo::argumentGPR2);
1065         m_jit.move(JITCompiler::TrustedImmPtr(pointer), GPRInfo::argumentGPR1);
1066         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1067
1068         appendCallWithExceptionCheck(operation);
1069         m_jit.move(GPRInfo::returnValueGPR, result);
1070     }
1071     void callOperation(J_DFGOperation_ESS operation, GPRReg result, int startConstant, int numConstants)
1072     {
1073         ASSERT(isFlushed());
1074
1075         m_jit.move(JITCompiler::TrustedImm32(numConstants), GPRInfo::argumentGPR2);
1076         m_jit.move(JITCompiler::TrustedImm32(startConstant), GPRInfo::argumentGPR1);
1077         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1078
1079         appendCallWithExceptionCheck(operation);
1080         m_jit.move(GPRInfo::returnValueGPR, result);
1081     }
1082     void callOperation(J_DFGOperation_EJP operation, GPRReg result, GPRReg arg1, void* pointer)
1083     {
1084         ASSERT(isFlushed());
1085
1086         m_jit.move(arg1, GPRInfo::argumentGPR1);
1087         m_jit.move(JITCompiler::TrustedImmPtr(pointer), GPRInfo::argumentGPR2);
1088         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1089
1090         appendCallWithExceptionCheck(operation);
1091         m_jit.move(GPRInfo::returnValueGPR, result);
1092     }
1093     void callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
1094     {
1095         callOperation((J_DFGOperation_EJP)operation, result, arg1, identifier);
1096     }
1097     void callOperation(J_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
1098     {
1099         ASSERT(isFlushed());
1100
1101         m_jit.move(arg1, GPRInfo::argumentGPR1);
1102         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1103
1104         appendCallWithExceptionCheck(operation);
1105         m_jit.move(GPRInfo::returnValueGPR, result);
1106     }
1107     void callOperation(Z_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
1108     {
1109         ASSERT(isFlushed());
1110
1111         m_jit.move(arg1, GPRInfo::argumentGPR1);
1112         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1113
1114         appendCallWithExceptionCheck(operation);
1115         m_jit.move(GPRInfo::returnValueGPR, result);
1116     }
1117     void callOperation(Z_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1118     {
1119         ASSERT(isFlushed());
1120
1121         setupStubArguments(arg1, arg2);
1122         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1123
1124         appendCallWithExceptionCheck(operation);
1125         m_jit.move(GPRInfo::returnValueGPR, result);
1126     }
1127     void callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1128     {
1129         ASSERT(isFlushed());
1130
1131         setupStubArguments(arg1, arg2);
1132         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1133
1134         appendCallWithExceptionCheck(operation);
1135         m_jit.move(GPRInfo::returnValueGPR, result);
1136     }
1137     void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1, GPRReg arg2, void* pointer)
1138     {
1139         ASSERT(isFlushed());
1140
1141         setupStubArguments(arg1, arg2);
1142         m_jit.move(JITCompiler::TrustedImmPtr(pointer), GPRInfo::argumentGPR3);
1143         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1144
1145         appendCallWithExceptionCheck(operation);
1146     }
1147     void callOperation(V_DFGOperation_EJJI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier)
1148     {
1149         callOperation((V_DFGOperation_EJJP)operation, arg1, arg2, identifier);
1150     }
1151     void callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
1152     {
1153         ASSERT(isFlushed());
1154
1155         setupStubArguments(arg1, arg2, arg3);
1156         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1157
1158         appendCallWithExceptionCheck(operation);
1159     }
1160     void callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
1161     {
1162         ASSERT(isFlushed());
1163
1164         setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
1165
1166         m_jit.appendCall(operation);
1167         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1168     }
1169
1170 #elif CPU(X86)
1171
1172     void setupResults(GPRReg tag, GPRReg payload)
1173     {
1174         setupTwoStubArgs<GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2>(payload, tag);
1175     }
1176
1177     // These methods add calls to C++ helper functions.
1178     void callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
1179     {
1180         ASSERT(isFlushed());
1181
1182         m_jit.push(JITCompiler::TrustedImm32(reinterpret_cast<int>(pointer)));
1183         m_jit.push(GPRInfo::callFrameRegister);
1184
1185         appendCallWithExceptionCheck(operation);
1186         setupResults(resultTag, resultPayload);
1187     }
1188     void callOperation(J_DFGOperation_EI operation, GPRReg resultTag, GPRReg resultPayload, Identifier* identifier)
1189     {
1190         callOperation((J_DFGOperation_EP)operation, resultTag, resultPayload, identifier);
1191     }
1192     void callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
1193     {
1194         ASSERT(isFlushed());
1195
1196         m_jit.push(JITCompiler::TrustedImm32(size));
1197         m_jit.push(JITCompiler::TrustedImm32(reinterpret_cast<int>(pointer)));
1198         m_jit.push(GPRInfo::callFrameRegister);
1199
1200         appendCallWithExceptionCheck(operation);
1201         setupResults(resultTag, resultPayload);
1202     }
1203     void callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, void* pointer)
1204     {
1205         ASSERT(isFlushed());
1206
1207         m_jit.push(JITCompiler::TrustedImm32(reinterpret_cast<int>(pointer)));
1208         m_jit.push(arg1Tag);
1209         m_jit.push(arg1Payload);
1210         m_jit.push(GPRInfo::callFrameRegister);
1211
1212         appendCallWithExceptionCheck(operation);
1213         setupResults(resultTag, resultPayload);
1214     }
1215     void callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, Identifier* identifier)
1216     {
1217         callOperation((J_DFGOperation_EJP)operation, resultTag, resultPayload, arg1Tag, arg1Payload, identifier);
1218     }
1219     void callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload)
1220     {
1221         ASSERT(isFlushed());
1222
1223         m_jit.push(arg1Tag);
1224         m_jit.push(arg1Payload);
1225         m_jit.push(GPRInfo::callFrameRegister);
1226
1227         appendCallWithExceptionCheck(operation);
1228         setupResults(resultTag, resultPayload);
1229     }
1230     void callOperation(Z_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
1231     {
1232         ASSERT(isFlushed());
1233
1234         m_jit.push(arg1Tag);
1235         m_jit.push(arg1Payload);
1236         m_jit.push(GPRInfo::callFrameRegister);
1237
1238         appendCallWithExceptionCheck(operation);
1239         m_jit.move(GPRInfo::returnValueGPR, result);
1240     }
1241     void callOperation(Z_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
1242     {
1243         ASSERT(isFlushed());
1244
1245         m_jit.push(arg2Tag);
1246         m_jit.push(arg2Payload);
1247         m_jit.push(arg1Tag);
1248         m_jit.push(arg1Payload);
1249         m_jit.push(GPRInfo::callFrameRegister);
1250
1251         appendCallWithExceptionCheck(operation);
1252         m_jit.move(GPRInfo::returnValueGPR, result);
1253     }
1254     void callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
1255     {
1256         ASSERT(isFlushed());
1257
1258         m_jit.push(arg2Tag);
1259         m_jit.push(arg2Payload);
1260         m_jit.push(arg1Tag);
1261         m_jit.push(arg1Payload);
1262         m_jit.push(GPRInfo::callFrameRegister);
1263
1264         appendCallWithExceptionCheck(operation);
1265         setupResults(resultTag, resultPayload);
1266     }
1267     void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, void* pointer)
1268     {
1269         ASSERT(isFlushed());
1270
1271         m_jit.push(JITCompiler::TrustedImm32(reinterpret_cast<int>(pointer)));
1272         m_jit.push(arg2Tag);
1273         m_jit.push(arg2Payload);
1274         m_jit.push(arg1Tag);
1275         m_jit.push(arg1Payload);
1276         m_jit.push(GPRInfo::callFrameRegister);
1277
1278         appendCallWithExceptionCheck(operation);
1279     }
1280     void callOperation(V_DFGOperation_EJJI operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, Identifier* identifier)
1281     {
1282         callOperation((V_DFGOperation_EJJP)operation, arg1Tag, arg1Payload, arg2Tag, arg2Payload, identifier);
1283     }
1284     void callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
1285     {
1286         ASSERT(isFlushed());
1287
1288         m_jit.push(arg3Tag);
1289         m_jit.push(arg3Payload);
1290         m_jit.push(arg2Tag);
1291         m_jit.push(arg2Payload);
1292         m_jit.push(arg1Tag);
1293         m_jit.push(arg1Payload);
1294         m_jit.push(GPRInfo::callFrameRegister);
1295
1296         appendCallWithExceptionCheck(operation);
1297     }
1298
1299     void NO_RETURN callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
1300     {
1301         ASSERT(isFlushed());
1302
1303         // FIXME: Need to to pass doubles.
1304         ASSERT_NOT_REACHED();
1305         UNUSED_PARAM(arg1);
1306         UNUSED_PARAM(arg2);
1307
1308         m_jit.appendCall(operation);
1309         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1310     }
1311 #endif
1312
1313     JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
1314     {
1315         return m_jit.appendCallWithExceptionCheck(function, m_jit.graph()[m_compileIndex].codeOrigin);
1316     }
1317
1318     void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination)
1319     {
1320         m_branches.append(BranchRecord(jump, destination));
1321     }
1322
1323     void linkBranches()
1324     {
1325         for (size_t i = 0; i < m_branches.size(); ++i) {
1326             BranchRecord& branch = m_branches[i];
1327             branch.jump.linkTo(m_blockHeads[branch.destination], &m_jit);
1328         }
1329     }
1330
1331 #ifndef NDEBUG
1332     void dump(const char* label = 0);
1333 #endif
1334
1335 #if ENABLE(DFG_CONSISTENCY_CHECK)
1336     void checkConsistency();
1337 #else
1338     void checkConsistency() {}
1339 #endif
1340
1341     // The JIT, while also provides MacroAssembler functionality.
1342     JITCompiler& m_jit;
1343     // This flag is used to distinguish speculative and non-speculative
1344     // code generation. This is significant when filling spilled values
1345     // from the RegisterFile. When spilling we attempt to store information
1346     // as to the type of boxed value being stored (int32, double, cell), and
1347     // when filling on the speculative path we will retrieve this type info
1348     // where available. On the non-speculative path, however, we cannot rely
1349     // on the spill format info, since the a value being loaded might have
1350     // been spilled by either the speculative or non-speculative paths (where
1351     // we entered the non-speculative path on an intervening bail-out), and
1352     // the value may have been boxed differently on the two paths.
1353     bool m_isSpeculative;
1354     // The current node being generated.
1355     BlockIndex m_block;
1356     NodeIndex m_compileIndex;
1357     // Virtual and physical register maps.
1358     Vector<GenerationInfo, 32> m_generationInfo;
1359     RegisterBank<GPRInfo> m_gprs;
1360     RegisterBank<FPRInfo> m_fprs;
1361
1362     Vector<MacroAssembler::Label> m_blockHeads;
1363     struct BranchRecord {
1364         BranchRecord(MacroAssembler::Jump jump, BlockIndex destination)
1365             : jump(jump)
1366             , destination(destination)
1367         {
1368         }
1369
1370         MacroAssembler::Jump jump;
1371         BlockIndex destination;
1372     };
1373     Vector<BranchRecord, 8> m_branches;
1374 };
1375
1376 // === Operand types ===
1377 //
1378 // IntegerOperand, DoubleOperand and JSValueOperand.
1379 //
1380 // These classes are used to lock the operands to a node into machine
1381 // registers. These classes implement of pattern of locking a value
1382 // into register at the point of construction only if it is already in
1383 // registers, and otherwise loading it lazily at the point it is first
1384 // used. We do so in order to attempt to avoid spilling one operand
1385 // in order to make space available for another.
1386
1387 class IntegerOperand {
1388 public:
1389     explicit IntegerOperand(JITCodeGenerator* jit, NodeIndex index)
1390         : m_jit(jit)
1391         , m_index(index)
1392         , m_gprOrInvalid(InvalidGPRReg)
1393 #ifndef NDEBUG
1394         , m_format(DataFormatNone)
1395 #endif
1396     {
1397         ASSERT(m_jit);
1398         if (jit->isFilled(index))
1399             gpr();
1400     }
1401
1402     ~IntegerOperand()
1403     {
1404         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1405         m_jit->unlock(m_gprOrInvalid);
1406     }
1407
1408     NodeIndex index() const
1409     {
1410         return m_index;
1411     }
1412
1413     DataFormat format()
1414     {
1415         gpr(); // m_format is set when m_gpr is locked.
1416         ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
1417         return m_format;
1418     }
1419
1420     GPRReg gpr()
1421     {
1422         if (m_gprOrInvalid == InvalidGPRReg)
1423             m_gprOrInvalid = m_jit->fillInteger(index(), m_format);
1424         return m_gprOrInvalid;
1425     }
1426     
1427     void use()
1428     {
1429         m_jit->use(m_index);
1430     }
1431
1432 private:
1433     JITCodeGenerator* m_jit;
1434     NodeIndex m_index;
1435     GPRReg m_gprOrInvalid;
1436     DataFormat m_format;
1437 };
1438
1439 class DoubleOperand {
1440 public:
1441     explicit DoubleOperand(JITCodeGenerator* jit, NodeIndex index)
1442         : m_jit(jit)
1443         , m_index(index)
1444         , m_fprOrInvalid(InvalidFPRReg)
1445     {
1446         ASSERT(m_jit);
1447         if (jit->isFilledDouble(index))
1448             fpr();
1449     }
1450
1451     ~DoubleOperand()
1452     {
1453         ASSERT(m_fprOrInvalid != InvalidFPRReg);
1454         m_jit->unlock(m_fprOrInvalid);
1455     }
1456
1457     NodeIndex index() const
1458     {
1459         return m_index;
1460     }
1461
1462     FPRReg fpr()
1463     {
1464         if (m_fprOrInvalid == InvalidFPRReg)
1465             m_fprOrInvalid = m_jit->fillDouble(index());
1466         return m_fprOrInvalid;
1467     }
1468     
1469     void use()
1470     {
1471         m_jit->use(m_index);
1472     }
1473
1474 private:
1475     JITCodeGenerator* m_jit;
1476     NodeIndex m_index;
1477     FPRReg m_fprOrInvalid;
1478 };
1479
1480 class JSValueOperand {
1481 public:
1482     explicit JSValueOperand(JITCodeGenerator* jit, NodeIndex index)
1483         : m_jit(jit)
1484         , m_index(index)
1485 #if USE(JSVALUE64)
1486         , m_gprOrInvalid(InvalidGPRReg)
1487 #elif USE(JSVALUE32_64)
1488         , m_isDouble(false)
1489 #endif
1490     {
1491         ASSERT(m_jit);
1492 #if USE(JSVALUE64)
1493         if (jit->isFilled(index))
1494             gpr();
1495 #elif USE(JSVALUE32_64)
1496         m_register.pair.tagGPR = InvalidGPRReg;
1497         m_register.pair.payloadGPR = InvalidGPRReg;
1498         if (jit->isFilled(index))
1499             fill();
1500 #endif
1501     }
1502
1503     ~JSValueOperand()
1504     {
1505 #if USE(JSVALUE64)
1506         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1507         m_jit->unlock(m_gprOrInvalid);
1508 #elif USE(JSVALUE32_64)
1509         if (m_isDouble) {
1510             ASSERT(m_register.fpr != InvalidFPRReg);
1511             m_jit->unlock(m_register.fpr);
1512         } else {
1513             ASSERT(m_register.pair.tagGPR != InvalidGPRReg && m_register.pair.payloadGPR != InvalidGPRReg);
1514             m_jit->unlock(m_register.pair.tagGPR);
1515             m_jit->unlock(m_register.pair.payloadGPR);
1516         }
1517 #endif
1518     }
1519
1520     NodeIndex index() const
1521     {
1522         return m_index;
1523     }
1524
1525 #if USE(JSVALUE64)
1526     GPRReg gpr()
1527     {
1528         if (m_gprOrInvalid == InvalidGPRReg)
1529             m_gprOrInvalid = m_jit->fillJSValue(index());
1530         return m_gprOrInvalid;
1531     }
1532 #elif USE(JSVALUE32_64)
1533     bool isDouble() { return m_isDouble; }
1534
1535     void fill()
1536     {
1537         if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg)
1538             m_isDouble = !m_jit->fillJSValue(index(), m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);
1539     }
1540
1541     GPRReg tagGPR()
1542     {
1543         fill();
1544         ASSERT(!m_isDouble);
1545         return m_register.pair.tagGPR;
1546     }
1547
1548     GPRReg payloadGPR()
1549     {
1550         fill();
1551         ASSERT(!m_isDouble);
1552         return m_register.pair.payloadGPR;
1553     }
1554
1555     FPRReg fpr()
1556     {
1557         fill();
1558         ASSERT(m_isDouble);
1559         return m_register.fpr;
1560     }
1561 #endif
1562
1563     void use()
1564     {
1565         m_jit->use(m_index);
1566     }
1567
1568 private:
1569     JITCodeGenerator* m_jit;
1570     NodeIndex m_index;
1571 #if USE(JSVALUE64)
1572     GPRReg m_gprOrInvalid;
1573 #elif USE(JSVALUE32_64)
1574     union {
1575         struct {
1576             GPRReg tagGPR;
1577             GPRReg payloadGPR;
1578         } pair;
1579         FPRReg fpr;
1580     } m_register;
1581     bool m_isDouble;
1582 #endif
1583 };
1584
1585 class StorageOperand {
1586 public:
1587     explicit StorageOperand(JITCodeGenerator* jit, NodeIndex index)
1588         : m_jit(jit)
1589         , m_index(index)
1590         , m_gprOrInvalid(InvalidGPRReg)
1591     {
1592         ASSERT(m_jit);
1593         if (jit->isFilled(index))
1594             gpr();
1595     }
1596     
1597     ~StorageOperand()
1598     {
1599         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1600         m_jit->unlock(m_gprOrInvalid);
1601     }
1602     
1603     NodeIndex index() const
1604     {
1605         return m_index;
1606     }
1607     
1608     GPRReg gpr()
1609     {
1610         if (m_gprOrInvalid == InvalidGPRReg)
1611             m_gprOrInvalid = m_jit->fillStorage(index());
1612         return m_gprOrInvalid;
1613     }
1614     
1615     void use()
1616     {
1617         m_jit->use(m_index);
1618     }
1619     
1620 private:
1621     JITCodeGenerator* m_jit;
1622     NodeIndex m_index;
1623     GPRReg m_gprOrInvalid;
1624 };
1625
1626
1627 // === Temporaries ===
1628 //
1629 // These classes are used to allocate temporary registers.
1630 // A mechanism is provided to attempt to reuse the registers
1631 // currently allocated to child nodes whose value is consumed
1632 // by, and not live after, this operation.
1633
1634 class GPRTemporary {
1635 public:
1636     GPRTemporary();
1637     GPRTemporary(JITCodeGenerator*);
1638     GPRTemporary(JITCodeGenerator*, GPRReg specific);
1639     GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&);
1640     GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&, SpeculateIntegerOperand&);
1641     GPRTemporary(JITCodeGenerator*, SpeculateStrictInt32Operand&);
1642     GPRTemporary(JITCodeGenerator*, IntegerOperand&);
1643     GPRTemporary(JITCodeGenerator*, IntegerOperand&, IntegerOperand&);
1644     GPRTemporary(JITCodeGenerator*, SpeculateCellOperand&);
1645     GPRTemporary(JITCodeGenerator*, SpeculateBooleanOperand&);
1646 #if USE(JSVALUE64)
1647     GPRTemporary(JITCodeGenerator*, JSValueOperand&);
1648 #elif USE(JSVALUE32_64)
1649     GPRTemporary(JITCodeGenerator*, JSValueOperand&, bool tag = true);
1650 #endif
1651     GPRTemporary(JITCodeGenerator*, StorageOperand&);
1652
1653     void adopt(GPRTemporary&);
1654
1655     ~GPRTemporary()
1656     {
1657         if (m_jit && m_gpr != InvalidGPRReg)
1658             m_jit->unlock(gpr());
1659     }
1660
1661     GPRReg gpr()
1662     {
1663         // In some cases we have lazy allocation.
1664         if (m_jit && m_gpr == InvalidGPRReg)
1665             m_gpr = m_jit->allocate();
1666         return m_gpr;
1667     }
1668
1669 private:
1670     JITCodeGenerator* m_jit;
1671     GPRReg m_gpr;
1672 };
1673
1674 class FPRTemporary {
1675 public:
1676     FPRTemporary(JITCodeGenerator*);
1677     FPRTemporary(JITCodeGenerator*, DoubleOperand&);
1678     FPRTemporary(JITCodeGenerator*, DoubleOperand&, DoubleOperand&);
1679     FPRTemporary(JITCodeGenerator*, SpeculateDoubleOperand&);
1680     FPRTemporary(JITCodeGenerator*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
1681 #if USE(JSVALUE32_64)
1682     FPRTemporary(JITCodeGenerator*, JSValueOperand&);
1683 #endif
1684
1685     ~FPRTemporary()
1686     {
1687         m_jit->unlock(fpr());
1688     }
1689
1690     FPRReg fpr() const
1691     {
1692         ASSERT(m_fpr != InvalidFPRReg);
1693         return m_fpr;
1694     }
1695
1696 protected:
1697     FPRTemporary(JITCodeGenerator* jit, FPRReg lockedFPR)
1698         : m_jit(jit)
1699         , m_fpr(lockedFPR)
1700     {
1701     }
1702
1703 private:
1704     JITCodeGenerator* m_jit;
1705     FPRReg m_fpr;
1706 };
1707
1708
1709 // === Results ===
1710 //
1711 // These classes lock the result of a call to a C++ helper function.
1712
1713 class GPRResult : public GPRTemporary {
1714 public:
1715     GPRResult(JITCodeGenerator* jit)
1716         : GPRTemporary(jit, GPRInfo::returnValueGPR)
1717     {
1718     }
1719 };
1720
1721 #if USE(JSVALUE32_64)
1722 class GPRResult2 : public GPRTemporary {
1723 public:
1724     GPRResult2(JITCodeGenerator* jit)
1725         : GPRTemporary(jit, GPRInfo::returnValueGPR2)
1726     {
1727     }
1728 };
1729 #endif
1730
1731 class FPRResult : public FPRTemporary {
1732 public:
1733     FPRResult(JITCodeGenerator* jit)
1734         : FPRTemporary(jit, lockedResult(jit))
1735     {
1736     }
1737
1738 private:
1739     static FPRReg lockedResult(JITCodeGenerator* jit)
1740     {
1741         jit->lock(FPRInfo::returnValueFPR);
1742         return FPRInfo::returnValueFPR;
1743     }
1744 };
1745
1746 } } // namespace JSC::DFG
1747
1748 #endif
1749 #endif
1750