d13ed8a2128b398ebb69b76db7daf89217ac4599
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.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 DFGSpeculativeJIT_h
27 #define DFGSpeculativeJIT_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGAbstractState.h"
32 #include "DFGGenerationInfo.h"
33 #include "DFGJITCompiler.h"
34 #include "DFGOSRExit.h"
35 #include "DFGOperations.h"
36 #include "MarkedAllocator.h"
37 #include "ValueRecovery.h"
38
39 namespace JSC { namespace DFG {
40
41 class JSValueOperand;
42 class SpeculativeJIT;
43 class SpeculateIntegerOperand;
44 class SpeculateStrictInt32Operand;
45 class SpeculateDoubleOperand;
46 class SpeculateCellOperand;
47 class SpeculateBooleanOperand;
48
49
50 enum ValueSourceKind {
51     SourceNotSet,
52     ValueInRegisterFile,
53     Int32InRegisterFile,
54     CellInRegisterFile,
55     BooleanInRegisterFile,
56     DoubleInRegisterFile,
57     HaveNode
58 };
59
60 class ValueSource {
61 public:
62     ValueSource()
63         : m_nodeIndex(nodeIndexFromKind(SourceNotSet))
64     {
65     }
66     
67     explicit ValueSource(ValueSourceKind valueSourceKind)
68         : m_nodeIndex(nodeIndexFromKind(valueSourceKind))
69     {
70         ASSERT(kind() != SourceNotSet);
71         ASSERT(kind() != HaveNode);
72     }
73     
74     explicit ValueSource(NodeIndex nodeIndex)
75         : m_nodeIndex(nodeIndex)
76     {
77         ASSERT(kind() == HaveNode);
78     }
79     
80     static ValueSource forPrediction(PredictedType prediction)
81     {
82         if (isInt32Prediction(prediction))
83             return ValueSource(Int32InRegisterFile);
84         if (isArrayPrediction(prediction) || isByteArrayPrediction(prediction))
85             return ValueSource(CellInRegisterFile);
86         if (isBooleanPrediction(prediction))
87             return ValueSource(BooleanInRegisterFile);
88         return ValueSource(ValueInRegisterFile);
89     }
90     
91     bool isSet() const
92     {
93         return kindFromNodeIndex(m_nodeIndex) != SourceNotSet;
94     }
95     
96     ValueSourceKind kind() const
97     {
98         return kindFromNodeIndex(m_nodeIndex);
99     }
100     
101     NodeIndex nodeIndex() const
102     {
103         ASSERT(kind() == HaveNode);
104         return m_nodeIndex;
105     }
106     
107     void dump(FILE* out) const;
108     
109 private:
110     static NodeIndex nodeIndexFromKind(ValueSourceKind kind)
111     {
112         ASSERT(kind >= SourceNotSet && kind < HaveNode);
113         return NoNode - kind;
114     }
115     
116     static ValueSourceKind kindFromNodeIndex(NodeIndex nodeIndex)
117     {
118         unsigned kind = static_cast<unsigned>(NoNode - nodeIndex);
119         if (kind >= static_cast<unsigned>(HaveNode))
120             return HaveNode;
121         return static_cast<ValueSourceKind>(kind);
122     }
123     
124     NodeIndex m_nodeIndex;
125 };
126
127
128 enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandDouble, GeneratedOperandJSValue};
129
130 // === SpeculativeJIT ===
131 //
132 // The SpeculativeJIT is used to generate a fast, but potentially
133 // incomplete code path for the dataflow. When code generating
134 // we may make assumptions about operand types, dynamically check,
135 // and bail-out to an alternate code path if these checks fail.
136 // Importantly, the speculative code path cannot be reentered once
137 // a speculative check has failed. This allows the SpeculativeJIT
138 // to propagate type information (including information that has
139 // only speculatively been asserted) through the dataflow.
140 class SpeculativeJIT {
141     friend struct OSRExit;
142 private:
143     typedef JITCompiler::TrustedImm32 TrustedImm32;
144     typedef JITCompiler::Imm32 Imm32;
145     typedef JITCompiler::TrustedImmPtr TrustedImmPtr;
146     typedef JITCompiler::ImmPtr ImmPtr;
147
148     // These constants are used to set priorities for spill order for
149     // the register allocator.
150 #if USE(JSVALUE64)
151     enum SpillOrder {
152         SpillOrderConstant = 1, // no spill, and cheap fill
153         SpillOrderSpilled  = 2, // no spill
154         SpillOrderJS       = 4, // needs spill
155         SpillOrderCell     = 4, // needs spill
156         SpillOrderStorage  = 4, // needs spill
157         SpillOrderInteger  = 5, // needs spill and box
158         SpillOrderBoolean  = 5, // needs spill and box
159         SpillOrderDouble   = 6, // needs spill and convert
160     };
161 #elif USE(JSVALUE32_64)
162     enum SpillOrder {
163         SpillOrderConstant = 1, // no spill, and cheap fill
164         SpillOrderSpilled  = 2, // no spill
165         SpillOrderJS       = 4, // needs spill
166         SpillOrderStorage  = 4, // needs spill
167         SpillOrderDouble   = 4, // needs spill
168         SpillOrderInteger  = 5, // needs spill and box
169         SpillOrderCell     = 5, // needs spill and box
170         SpillOrderBoolean  = 5, // needs spill and box
171     };
172 #endif
173
174     enum UseChildrenMode { CallUseChildren, UseChildrenCalledExplicitly };
175     
176 public:
177     SpeculativeJIT(JITCompiler&);
178
179     bool compile();
180     void createOSREntries();
181     void linkOSREntries(LinkBuffer&);
182
183     Node& at(NodeIndex nodeIndex)
184     {
185         return m_jit.graph()[nodeIndex];
186     }
187     Node& at(Edge nodeUse)
188     {
189         return at(nodeUse.index());
190     }
191     
192     GPRReg fillInteger(NodeIndex, DataFormat& returnFormat);
193     FPRReg fillDouble(NodeIndex);
194 #if USE(JSVALUE64)
195     GPRReg fillJSValue(NodeIndex);
196 #elif USE(JSVALUE32_64)
197     bool fillJSValue(NodeIndex, GPRReg&, GPRReg&, FPRReg&);
198 #endif
199     GPRReg fillStorage(NodeIndex);
200
201     // lock and unlock GPR & FPR registers.
202     void lock(GPRReg reg)
203     {
204         m_gprs.lock(reg);
205     }
206     void lock(FPRReg reg)
207     {
208         m_fprs.lock(reg);
209     }
210     void unlock(GPRReg reg)
211     {
212         m_gprs.unlock(reg);
213     }
214     void unlock(FPRReg reg)
215     {
216         m_fprs.unlock(reg);
217     }
218
219     // Used to check whether a child node is on its last use,
220     // and its machine registers may be reused.
221     bool canReuse(NodeIndex nodeIndex)
222     {
223         VirtualRegister virtualRegister = at(nodeIndex).virtualRegister();
224         GenerationInfo& info = m_generationInfo[virtualRegister];
225         return info.canReuse();
226     }
227     bool canReuse(Edge nodeUse)
228     {
229         return canReuse(nodeUse.index());
230     }
231     GPRReg reuse(GPRReg reg)
232     {
233         m_gprs.lock(reg);
234         return reg;
235     }
236     FPRReg reuse(FPRReg reg)
237     {
238         m_fprs.lock(reg);
239         return reg;
240     }
241
242     // Allocate a gpr/fpr.
243     GPRReg allocate()
244     {
245         VirtualRegister spillMe;
246         GPRReg gpr = m_gprs.allocate(spillMe);
247         if (spillMe != InvalidVirtualRegister) {
248 #if USE(JSVALUE32_64)
249             GenerationInfo& info = m_generationInfo[spillMe];
250             ASSERT(info.registerFormat() != DataFormatJSDouble);
251             if ((info.registerFormat() & DataFormatJS))
252                 m_gprs.release(info.tagGPR() == gpr ? info.payloadGPR() : info.tagGPR());
253 #endif
254             spill(spillMe);
255         }
256         return gpr;
257     }
258     GPRReg allocate(GPRReg specific)
259     {
260         VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
261         if (spillMe != InvalidVirtualRegister) {
262 #if USE(JSVALUE32_64)
263             GenerationInfo& info = m_generationInfo[spillMe];
264             ASSERT(info.registerFormat() != DataFormatJSDouble);
265             if ((info.registerFormat() & DataFormatJS))
266                 m_gprs.release(info.tagGPR() == specific ? info.payloadGPR() : info.tagGPR());
267 #endif
268             spill(spillMe);
269         }
270         return specific;
271     }
272     GPRReg tryAllocate()
273     {
274         return m_gprs.tryAllocate();
275     }
276     FPRReg fprAllocate()
277     {
278         VirtualRegister spillMe;
279         FPRReg fpr = m_fprs.allocate(spillMe);
280         if (spillMe != InvalidVirtualRegister)
281             spill(spillMe);
282         return fpr;
283     }
284
285     // Check whether a VirtualRegsiter is currently in a machine register.
286     // We use this when filling operands to fill those that are already in
287     // machine registers first (by locking VirtualRegsiters that are already
288     // in machine register before filling those that are not we attempt to
289     // avoid spilling values we will need immediately).
290     bool isFilled(NodeIndex nodeIndex)
291     {
292         VirtualRegister virtualRegister = at(nodeIndex).virtualRegister();
293         GenerationInfo& info = m_generationInfo[virtualRegister];
294         return info.registerFormat() != DataFormatNone;
295     }
296     bool isFilledDouble(NodeIndex nodeIndex)
297     {
298         VirtualRegister virtualRegister = at(nodeIndex).virtualRegister();
299         GenerationInfo& info = m_generationInfo[virtualRegister];
300         return info.registerFormat() == DataFormatDouble;
301     }
302
303     // Called on an operand once it has been consumed by a parent node.
304     void use(NodeIndex nodeIndex)
305     {
306         VirtualRegister virtualRegister = at(nodeIndex).virtualRegister();
307         GenerationInfo& info = m_generationInfo[virtualRegister];
308
309         // use() returns true when the value becomes dead, and any
310         // associated resources may be freed.
311         if (!info.use())
312             return;
313
314         // Release the associated machine registers.
315         DataFormat registerFormat = info.registerFormat();
316 #if USE(JSVALUE64)
317         if (registerFormat == DataFormatDouble)
318             m_fprs.release(info.fpr());
319         else if (registerFormat != DataFormatNone)
320             m_gprs.release(info.gpr());
321 #elif USE(JSVALUE32_64)
322         if (registerFormat == DataFormatDouble || registerFormat == DataFormatJSDouble)
323             m_fprs.release(info.fpr());
324         else if (registerFormat & DataFormatJS) {
325             m_gprs.release(info.tagGPR());
326             m_gprs.release(info.payloadGPR());
327         } else if (registerFormat != DataFormatNone)
328             m_gprs.release(info.gpr());
329 #endif
330     }
331     void use(Edge nodeUse)
332     {
333         use(nodeUse.index());
334     }
335
336     static void markCellCard(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2);
337     static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind);
338
339     void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
340     void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
341     void writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg);
342
343     static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
344     {
345         if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0)
346             return GPRInfo::regT0;
347
348         if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1)
349             return GPRInfo::regT1;
350
351         if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2)
352             return GPRInfo::regT2;
353
354         if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3)
355             return GPRInfo::regT3;
356
357         return GPRInfo::regT4;
358     }
359
360     // Called by the speculative operand types, below, to fill operand to
361     // machine registers, implicitly generating speculation checks as needed.
362     GPRReg fillSpeculateInt(NodeIndex, DataFormat& returnFormat);
363     GPRReg fillSpeculateIntStrict(NodeIndex);
364     FPRReg fillSpeculateDouble(NodeIndex);
365     GPRReg fillSpeculateCell(NodeIndex);
366     GPRReg fillSpeculateBoolean(NodeIndex);
367     GeneratedOperandType checkGeneratedTypeForToInt32(NodeIndex);
368
369 private:
370     void compile(Node&);
371     void compileMovHint(Node&);
372     void compile(BasicBlock&);
373
374     void checkArgumentTypes();
375
376     void clearGenerationInfo();
377
378     // These methods are used when generating 'unexpected'
379     // calls out from JIT code to C++ helper routines -
380     // they spill all live values to the appropriate
381     // slots in the RegisterFile without changing any state
382     // in the GenerationInfo.
383     void silentSpillGPR(VirtualRegister spillMe, GPRReg source)
384     {
385         GenerationInfo& info = m_generationInfo[spillMe];
386         ASSERT(info.registerFormat() != DataFormatNone);
387         ASSERT(info.registerFormat() != DataFormatDouble);
388
389         if (!info.needsSpill())
390             return;
391
392         DataFormat registerFormat = info.registerFormat();
393
394 #if USE(JSVALUE64)
395         ASSERT(info.gpr() == source);
396         if (registerFormat == DataFormatInteger)
397             m_jit.store32(source, JITCompiler::addressFor(spillMe));
398         else {
399             ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell || registerFormat == DataFormatStorage);
400             m_jit.storePtr(source, JITCompiler::addressFor(spillMe));
401         }
402 #elif USE(JSVALUE32_64)
403         if (registerFormat & DataFormatJS) {
404             ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
405             m_jit.store32(source, source == info.tagGPR() ? JITCompiler::tagFor(spillMe) : JITCompiler::payloadFor(spillMe));
406         } else {
407             ASSERT(info.gpr() == source);
408             m_jit.store32(source, JITCompiler::payloadFor(spillMe));
409         }
410 #endif
411     }
412     void silentSpillFPR(VirtualRegister spillMe, FPRReg source)
413     {
414         GenerationInfo& info = m_generationInfo[spillMe];
415         ASSERT(info.registerFormat() == DataFormatDouble);
416
417         if (!info.needsSpill()) {
418             // it's either a constant or it's already been spilled
419             ASSERT(at(info.nodeIndex()).hasConstant() || info.spillFormat() != DataFormatNone);
420             return;
421         }
422         
423         // it's neither a constant nor has it been spilled.
424         ASSERT(!at(info.nodeIndex()).hasConstant());
425         ASSERT(info.spillFormat() == DataFormatNone);
426         ASSERT(info.fpr() == source);
427
428         m_jit.storeDouble(source, JITCompiler::addressFor(spillMe));
429     }
430
431     void silentFillGPR(VirtualRegister spillMe, GPRReg target)
432     {
433         GenerationInfo& info = m_generationInfo[spillMe];
434
435         NodeIndex nodeIndex = info.nodeIndex();
436         Node& node = at(nodeIndex);
437         ASSERT(info.registerFormat() != DataFormatNone);
438         ASSERT(info.registerFormat() != DataFormatDouble);
439         DataFormat registerFormat = info.registerFormat();
440
441         if (registerFormat == DataFormatInteger) {
442             ASSERT(info.gpr() == target);
443             ASSERT(isJSInteger(info.registerFormat()));
444             if (node.hasConstant()) {
445                 ASSERT(isInt32Constant(nodeIndex));
446                 m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), target);
447             } else
448                 m_jit.load32(JITCompiler::payloadFor(spillMe), target);
449             return;
450         }
451         
452         if (registerFormat == DataFormatBoolean) {
453 #if USE(JSVALUE64)
454             ASSERT_NOT_REACHED();
455 #elif USE(JSVALUE32_64)
456             ASSERT(info.gpr() == target);
457             if (node.hasConstant()) {
458                 ASSERT(isBooleanConstant(nodeIndex));
459                 m_jit.move(TrustedImm32(valueOfBooleanConstant(nodeIndex)), target);
460             } else
461                 m_jit.load32(JITCompiler::payloadFor(spillMe), target);
462 #endif
463             return;
464         }
465
466         if (registerFormat == DataFormatCell) {
467             ASSERT(info.gpr() == target);
468             if (node.hasConstant()) {
469                 JSValue value = valueOfJSConstant(nodeIndex);
470                 ASSERT(value.isCell());
471                 m_jit.move(TrustedImmPtr(value.asCell()), target);
472             } else
473                 m_jit.loadPtr(JITCompiler::payloadFor(spillMe), target);
474             return;
475         }
476
477         if (registerFormat == DataFormatStorage) {
478             ASSERT(info.gpr() == target);
479             m_jit.loadPtr(JITCompiler::addressFor(spillMe), target);
480             return;
481         }
482
483         ASSERT(registerFormat & DataFormatJS);
484 #if USE(JSVALUE64)
485         ASSERT(info.gpr() == target);
486         if (node.hasConstant()) {
487             if (valueOfJSConstant(nodeIndex).isCell())
488                 m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex).asTrustedImmPtr(), target);
489             else
490                 m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), target);
491         } else if (info.spillFormat() == DataFormatInteger) {
492             ASSERT(registerFormat == DataFormatJSInteger);
493             m_jit.load32(JITCompiler::payloadFor(spillMe), target);
494             m_jit.orPtr(GPRInfo::tagTypeNumberRegister, target);
495         } else if (info.spillFormat() == DataFormatDouble) {
496             ASSERT(registerFormat == DataFormatJSDouble);
497             m_jit.loadPtr(JITCompiler::addressFor(spillMe), target);
498             m_jit.subPtr(GPRInfo::tagTypeNumberRegister, target);
499         } else
500             m_jit.loadPtr(JITCompiler::addressFor(spillMe), target);
501 #else
502         ASSERT(info.tagGPR() == target || info.payloadGPR() == target);
503         if (node.hasConstant()) {
504             JSValue v = valueOfJSConstant(nodeIndex);
505             m_jit.move(info.tagGPR() == target ? Imm32(v.tag()) : Imm32(v.payload()), target);
506         } else if (info.payloadGPR() == target)
507             m_jit.load32(JITCompiler::payloadFor(spillMe), target);
508         else { // Fill the Tag
509             switch (info.spillFormat()) {
510             case DataFormatInteger:
511                 ASSERT(registerFormat == DataFormatJSInteger);
512                 m_jit.move(TrustedImm32(JSValue::Int32Tag), target);
513                 break;
514             case DataFormatCell:
515                 ASSERT(registerFormat == DataFormatJSCell);
516                 m_jit.move(TrustedImm32(JSValue::CellTag), target);
517                 break;
518             case DataFormatBoolean:
519                 ASSERT(registerFormat == DataFormatJSBoolean);
520                 m_jit.move(TrustedImm32(JSValue::BooleanTag), target);
521                 break;
522             default:
523                 m_jit.load32(JITCompiler::tagFor(spillMe), target);
524                 break;
525             }
526         }
527 #endif
528     }
529
530     void silentFillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg target)
531     {
532         GenerationInfo& info = m_generationInfo[spillMe];
533         ASSERT(info.fpr() == target);
534
535         NodeIndex nodeIndex = info.nodeIndex();
536         Node& node = at(nodeIndex);
537 #if USE(JSVALUE64)
538         ASSERT(info.registerFormat() == DataFormatDouble);
539
540         if (node.hasConstant()) {
541             ASSERT(isNumberConstant(nodeIndex));
542             m_jit.move(ImmPtr(bitwise_cast<void*>(valueOfNumberConstant(nodeIndex))), canTrample);
543             m_jit.movePtrToDouble(canTrample, target);
544             return;
545         }
546         
547         if (info.spillFormat() != DataFormatNone && info.spillFormat() != DataFormatDouble) {
548             // it was already spilled previously and not as a double, which means we need unboxing.
549             ASSERT(info.spillFormat() & DataFormatJS);
550             m_jit.loadPtr(JITCompiler::addressFor(spillMe), canTrample);
551             unboxDouble(canTrample, target);
552             return;
553         }
554
555         m_jit.loadDouble(JITCompiler::addressFor(spillMe), target);
556 #elif USE(JSVALUE32_64)
557         UNUSED_PARAM(canTrample);
558         ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble);
559         if (node.hasConstant()) {
560             ASSERT(isNumberConstant(nodeIndex));
561             m_jit.loadDouble(addressOfDoubleConstant(nodeIndex), target);
562         } else
563             m_jit.loadDouble(JITCompiler::addressFor(spillMe), target);
564 #endif
565     }
566
567     void silentSpillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg)
568     {
569         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
570             GPRReg gpr = iter.regID();
571             if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2)
572                 silentSpillGPR(iter.name(), gpr);
573         }
574         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
575             if (iter.name() != InvalidVirtualRegister)
576                 silentSpillFPR(iter.name(), iter.regID());
577         }
578     }
579     void silentSpillAllRegisters(FPRReg exclude)
580     {
581         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
582             if (iter.name() != InvalidVirtualRegister)
583                 silentSpillGPR(iter.name(), iter.regID());
584         }
585         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
586             FPRReg fpr = iter.regID();
587             if (iter.name() != InvalidVirtualRegister && fpr != exclude)
588                 silentSpillFPR(iter.name(), fpr);
589         }
590     }
591
592     void silentFillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg)
593     {
594         GPRReg canTrample = GPRInfo::regT0;
595         if (exclude == GPRInfo::regT0)
596             canTrample = GPRInfo::regT1;
597         
598         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
599             if (iter.name() != InvalidVirtualRegister)
600                 silentFillFPR(iter.name(), canTrample, iter.regID());
601         }
602         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
603             GPRReg gpr = iter.regID();
604             if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2)
605                 silentFillGPR(iter.name(), gpr);
606         }
607     }
608     void silentFillAllRegisters(FPRReg exclude)
609     {
610         GPRReg canTrample = GPRInfo::regT0;
611         
612         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
613             FPRReg fpr = iter.regID();
614             if (iter.name() != InvalidVirtualRegister && fpr != exclude)
615                 silentFillFPR(iter.name(), canTrample, fpr);
616         }
617         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
618             if (iter.name() != InvalidVirtualRegister)
619                 silentFillGPR(iter.name(), iter.regID());
620         }
621     }
622
623     // These methods convert between doubles, and doubles boxed and JSValues.
624 #if USE(JSVALUE64)
625     GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
626     {
627         return m_jit.boxDouble(fpr, gpr);
628     }
629     FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
630     {
631         return m_jit.unboxDouble(gpr, fpr);
632     }
633     GPRReg boxDouble(FPRReg fpr)
634     {
635         return boxDouble(fpr, allocate());
636     }
637 #elif USE(JSVALUE32_64)
638     void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
639     {
640         m_jit.boxDouble(fpr, tagGPR, payloadGPR);
641     }
642     void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
643     {
644         m_jit.unboxDouble(tagGPR, payloadGPR, fpr, scratchFPR);
645     }
646 #endif
647
648     // Spill a VirtualRegister to the RegisterFile.
649     void spill(VirtualRegister spillMe)
650     {
651         GenerationInfo& info = m_generationInfo[spillMe];
652
653 #if USE(JSVALUE32_64)
654         if (info.registerFormat() == DataFormatNone) // it has been spilled. JS values which have two GPRs can reach here
655             return;
656 #endif
657         // Check the GenerationInfo to see if this value need writing
658         // to the RegisterFile - if not, mark it as spilled & return.
659         if (!info.needsSpill()) {
660             info.setSpilled();
661             return;
662         }
663
664         DataFormat spillFormat = info.registerFormat();
665         switch (spillFormat) {
666         case DataFormatStorage: {
667             // This is special, since it's not a JS value - as in it's not visible to JS
668             // code.
669             m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
670             info.spill(DataFormatStorage);
671             return;
672         }
673
674         case DataFormatInteger: {
675             m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
676             info.spill(DataFormatInteger);
677             return;
678         }
679
680 #if USE(JSVALUE64)
681         case DataFormatDouble: {
682             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
683             info.spill(DataFormatDouble);
684             return;
685         }
686             
687         default:
688             // The following code handles JSValues, int32s, and cells.
689             ASSERT(spillFormat == DataFormatCell || spillFormat & DataFormatJS);
690             
691             GPRReg reg = info.gpr();
692             // We need to box int32 and cell values ...
693             // but on JSVALUE64 boxing a cell is a no-op!
694             if (spillFormat == DataFormatInteger)
695                 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, reg);
696             
697             // Spill the value, and record it as spilled in its boxed form.
698             m_jit.storePtr(reg, JITCompiler::addressFor(spillMe));
699             info.spill((DataFormat)(spillFormat | DataFormatJS));
700             return;
701 #elif USE(JSVALUE32_64)
702         case DataFormatCell:
703         case DataFormatBoolean: {
704             m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
705             info.spill(spillFormat);
706             return;
707         }
708
709         case DataFormatDouble:
710         case DataFormatJSDouble: {
711             // On JSVALUE32_64 boxing a double is a no-op.
712             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
713             info.spill(DataFormatJSDouble);
714             return;
715         }
716
717         default:
718             // The following code handles JSValues.
719             ASSERT(spillFormat & DataFormatJS);
720             m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
721             m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
722             info.spill(spillFormat);
723             return;
724 #endif
725         }
726     }
727     
728     bool isStrictInt32(NodeIndex);
729     
730     bool isKnownInteger(NodeIndex);
731     bool isKnownNumeric(NodeIndex);
732     bool isKnownCell(NodeIndex);
733     
734     bool isKnownNotInteger(NodeIndex);
735     bool isKnownNotNumber(NodeIndex);
736
737     bool isKnownNotCell(NodeIndex);
738     
739     // Checks/accessors for constant values.
740     bool isConstant(NodeIndex nodeIndex) { return m_jit.graph().isConstant(nodeIndex); }
741     bool isJSConstant(NodeIndex nodeIndex) { return m_jit.graph().isJSConstant(nodeIndex); }
742     bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.graph().isInt32Constant(nodeIndex); }
743     bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.graph().isDoubleConstant(nodeIndex); }
744     bool isNumberConstant(NodeIndex nodeIndex) { return m_jit.graph().isNumberConstant(nodeIndex); }
745     bool isBooleanConstant(NodeIndex nodeIndex) { return m_jit.graph().isBooleanConstant(nodeIndex); }
746     bool isFunctionConstant(NodeIndex nodeIndex) { return m_jit.graph().isFunctionConstant(nodeIndex); }
747     int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.graph().valueOfInt32Constant(nodeIndex); }
748     double valueOfNumberConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfNumberConstant(nodeIndex); }
749     int32_t valueOfNumberConstantAsInt32(NodeIndex nodeIndex)
750     {
751         if (isInt32Constant(nodeIndex))
752             return valueOfInt32Constant(nodeIndex);
753         return JSC::toInt32(valueOfNumberConstant(nodeIndex));
754     }
755 #if USE(JSVALUE32_64)
756     void* addressOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.addressOfDoubleConstant(nodeIndex); }
757 #endif
758     JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfJSConstant(nodeIndex); }
759     bool valueOfBooleanConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfBooleanConstant(nodeIndex); }
760     JSFunction* valueOfFunctionConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfFunctionConstant(nodeIndex); }
761     bool isNullConstant(NodeIndex nodeIndex)
762     {
763         if (!isConstant(nodeIndex))
764             return false;
765         return valueOfJSConstant(nodeIndex).isNull();
766     }
767
768     Identifier* identifier(unsigned index)
769     {
770         return &m_jit.codeBlock()->identifier(index);
771     }
772
773     // Spill all VirtualRegisters back to the RegisterFile.
774     void flushRegisters()
775     {
776         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
777             if (iter.name() != InvalidVirtualRegister) {
778                 spill(iter.name());
779                 iter.release();
780             }
781         }
782         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
783             if (iter.name() != InvalidVirtualRegister) {
784                 spill(iter.name());
785                 iter.release();
786             }
787         }
788     }
789
790 #ifndef NDEBUG
791     // Used to ASSERT flushRegisters() has been called prior to
792     // calling out from JIT code to a C helper function.
793     bool isFlushed()
794     {
795         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
796             if (iter.name() != InvalidVirtualRegister)
797                 return false;
798         }
799         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
800             if (iter.name() != InvalidVirtualRegister)
801                 return false;
802         }
803         return true;
804     }
805 #endif
806
807 #if USE(JSVALUE64)
808     MacroAssembler::ImmPtr valueOfJSConstantAsImmPtr(NodeIndex nodeIndex)
809     {
810         return MacroAssembler::ImmPtr(JSValue::encode(valueOfJSConstant(nodeIndex)));
811     }
812 #endif
813
814     // Helper functions to enable code sharing in implementations of bit/shift ops.
815     void bitOp(NodeType op, int32_t imm, GPRReg op1, GPRReg result)
816     {
817         switch (op) {
818         case BitAnd:
819             m_jit.and32(Imm32(imm), op1, result);
820             break;
821         case BitOr:
822             m_jit.or32(Imm32(imm), op1, result);
823             break;
824         case BitXor:
825             m_jit.xor32(Imm32(imm), op1, result);
826             break;
827         default:
828             ASSERT_NOT_REACHED();
829         }
830     }
831     void bitOp(NodeType op, GPRReg op1, GPRReg op2, GPRReg result)
832     {
833         switch (op) {
834         case BitAnd:
835             m_jit.and32(op1, op2, result);
836             break;
837         case BitOr:
838             m_jit.or32(op1, op2, result);
839             break;
840         case BitXor:
841             m_jit.xor32(op1, op2, result);
842             break;
843         default:
844             ASSERT_NOT_REACHED();
845         }
846     }
847     void shiftOp(NodeType op, GPRReg op1, int32_t shiftAmount, GPRReg result)
848     {
849         switch (op) {
850         case BitRShift:
851             m_jit.rshift32(op1, Imm32(shiftAmount), result);
852             break;
853         case BitLShift:
854             m_jit.lshift32(op1, Imm32(shiftAmount), result);
855             break;
856         case BitURShift:
857             m_jit.urshift32(op1, Imm32(shiftAmount), result);
858             break;
859         default:
860             ASSERT_NOT_REACHED();
861         }
862     }
863     void shiftOp(NodeType op, GPRReg op1, GPRReg shiftAmount, GPRReg result)
864     {
865         switch (op) {
866         case BitRShift:
867             m_jit.rshift32(op1, shiftAmount, result);
868             break;
869         case BitLShift:
870             m_jit.lshift32(op1, shiftAmount, result);
871             break;
872         case BitURShift:
873             m_jit.urshift32(op1, shiftAmount, result);
874             break;
875         default:
876             ASSERT_NOT_REACHED();
877         }
878     }
879     
880     // Returns the index of the branch node if peephole is okay, UINT_MAX otherwise.
881     unsigned detectPeepHoleBranch()
882     {
883         BasicBlock* block = m_jit.graph().m_blocks[m_block].get();
884
885         // Check that no intervening nodes will be generated.
886         for (unsigned index = m_indexInBlock + 1; index < block->size() - 1; ++index) {
887             NodeIndex nodeIndex = block->at(index);
888             if (at(nodeIndex).shouldGenerate())
889                 return UINT_MAX;
890         }
891
892         // Check if the lastNode is a branch on this node.
893         Node& lastNode = at(block->last());
894         return lastNode.op() == Branch && lastNode.child1().index() == m_compileIndex ? block->size() - 1 : UINT_MAX;
895     }
896     
897     void nonSpeculativeValueToNumber(Node&);
898     void nonSpeculativeValueToInt32(Node&);
899     void nonSpeculativeUInt32ToNumber(Node&);
900
901     enum SpillRegistersMode { NeedToSpill, DontSpill };
902 #if USE(JSVALUE64)
903     JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
904     void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
905 #elif USE(JSVALUE32_64)
906     JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
907     void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
908 #endif
909
910     void nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert = false);
911     void nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert = false);
912     bool nonSpeculativeCompareNull(Node&, Edge operand, bool invert = false);
913     
914     void nonSpeculativePeepholeBranch(Node&, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction);
915     void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction);
916     bool nonSpeculativeCompare(Node&, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction);
917     
918     void nonSpeculativePeepholeStrictEq(Node&, NodeIndex branchNodeIndex, bool invert = false);
919     void nonSpeculativeNonPeepholeStrictEq(Node&, bool invert = false);
920     bool nonSpeculativeStrictEq(Node&, bool invert = false);
921     
922     void compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchAndResultReg);
923     void compileInstanceOf(Node&);
924     
925     // Access to our fixed callee CallFrame.
926     MacroAssembler::Address callFrameSlot(int slot)
927     {
928         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)));
929     }
930
931     // Access to our fixed callee CallFrame.
932     MacroAssembler::Address argumentSlot(int argument)
933     {
934         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)));
935     }
936
937     MacroAssembler::Address callFrameTagSlot(int slot)
938     {
939         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
940     }
941
942     MacroAssembler::Address callFramePayloadSlot(int slot)
943     {
944         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
945     }
946
947     MacroAssembler::Address argumentTagSlot(int argument)
948     {
949         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
950     }
951
952     MacroAssembler::Address argumentPayloadSlot(int argument)
953     {
954         return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
955     }
956
957     void emitCall(Node&);
958     
959     // Called once a node has completed code generation but prior to setting
960     // its result, to free up its children. (This must happen prior to setting
961     // the nodes result, since the node may have the same VirtualRegister as
962     // a child, and as such will use the same GeneratioInfo).
963     void useChildren(Node&);
964
965     // These method called to initialize the the GenerationInfo
966     // to describe the result of an operation.
967     void integerResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatInteger, UseChildrenMode mode = CallUseChildren)
968     {
969         Node& node = at(nodeIndex);
970         if (mode == CallUseChildren)
971             useChildren(node);
972
973         VirtualRegister virtualRegister = node.virtualRegister();
974         GenerationInfo& info = m_generationInfo[virtualRegister];
975
976         if (format == DataFormatInteger) {
977             m_jit.jitAssertIsInt32(reg);
978             m_gprs.retain(reg, virtualRegister, SpillOrderInteger);
979             info.initInteger(nodeIndex, node.refCount(), reg);
980         } else {
981 #if USE(JSVALUE64)
982             ASSERT(format == DataFormatJSInteger);
983             m_jit.jitAssertIsJSInt32(reg);
984             m_gprs.retain(reg, virtualRegister, SpillOrderJS);
985             info.initJSValue(nodeIndex, node.refCount(), reg, format);
986 #elif USE(JSVALUE32_64)
987             ASSERT_NOT_REACHED();
988 #endif
989         }
990     }
991     void integerResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode)
992     {
993         integerResult(reg, nodeIndex, DataFormatInteger, mode);
994     }
995     void noResult(NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
996     {
997         if (mode == UseChildrenCalledExplicitly)
998             return;
999         Node& node = at(nodeIndex);
1000         useChildren(node);
1001     }
1002     void cellResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
1003     {
1004         Node& node = at(nodeIndex);
1005         if (mode == CallUseChildren)
1006             useChildren(node);
1007
1008         VirtualRegister virtualRegister = node.virtualRegister();
1009         m_gprs.retain(reg, virtualRegister, SpillOrderCell);
1010         GenerationInfo& info = m_generationInfo[virtualRegister];
1011         info.initCell(nodeIndex, node.refCount(), reg);
1012     }
1013     void booleanResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
1014     {
1015         Node& node = at(nodeIndex);
1016         if (mode == CallUseChildren)
1017             useChildren(node);
1018
1019         VirtualRegister virtualRegister = node.virtualRegister();
1020         m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
1021         GenerationInfo& info = m_generationInfo[virtualRegister];
1022         info.initBoolean(nodeIndex, node.refCount(), reg);
1023     }
1024 #if USE(JSVALUE64)
1025     void jsValueResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
1026     {
1027         if (format == DataFormatJSInteger)
1028             m_jit.jitAssertIsJSInt32(reg);
1029         
1030         Node& node = at(nodeIndex);
1031         if (mode == CallUseChildren)
1032             useChildren(node);
1033
1034         VirtualRegister virtualRegister = node.virtualRegister();
1035         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
1036         GenerationInfo& info = m_generationInfo[virtualRegister];
1037         info.initJSValue(nodeIndex, node.refCount(), reg, format);
1038     }
1039     void jsValueResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode)
1040     {
1041         jsValueResult(reg, nodeIndex, DataFormatJS, mode);
1042     }
1043 #elif USE(JSVALUE32_64)
1044     void jsValueResult(GPRReg tag, GPRReg payload, NodeIndex nodeIndex, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
1045     {
1046         Node& node = at(nodeIndex);
1047         if (mode == CallUseChildren)
1048             useChildren(node);
1049
1050         VirtualRegister virtualRegister = node.virtualRegister();
1051         m_gprs.retain(tag, virtualRegister, SpillOrderJS);
1052         m_gprs.retain(payload, virtualRegister, SpillOrderJS);
1053         GenerationInfo& info = m_generationInfo[virtualRegister];
1054         info.initJSValue(nodeIndex, node.refCount(), tag, payload, format);
1055     }
1056     void jsValueResult(GPRReg tag, GPRReg payload, NodeIndex nodeIndex, UseChildrenMode mode)
1057     {
1058         jsValueResult(tag, payload, nodeIndex, DataFormatJS, mode);
1059     }
1060 #endif
1061     void storageResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
1062     {
1063         Node& node = at(nodeIndex);
1064         if (mode == CallUseChildren)
1065             useChildren(node);
1066         
1067         VirtualRegister virtualRegister = node.virtualRegister();
1068         m_gprs.retain(reg, virtualRegister, SpillOrderStorage);
1069         GenerationInfo& info = m_generationInfo[virtualRegister];
1070         info.initStorage(nodeIndex, node.refCount(), reg);
1071     }
1072     void doubleResult(FPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
1073     {
1074         Node& node = at(nodeIndex);
1075         if (mode == CallUseChildren)
1076             useChildren(node);
1077
1078         VirtualRegister virtualRegister = node.virtualRegister();
1079         m_fprs.retain(reg, virtualRegister, SpillOrderDouble);
1080         GenerationInfo& info = m_generationInfo[virtualRegister];
1081         info.initDouble(nodeIndex, node.refCount(), reg);
1082     }
1083     void initConstantInfo(NodeIndex nodeIndex)
1084     {
1085         ASSERT(isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex) || isJSConstant(nodeIndex));
1086         Node& node = at(nodeIndex);
1087         m_generationInfo[node.virtualRegister()].initConstant(nodeIndex, node.refCount());
1088     }
1089     
1090     // These methods add calls to C++ helper functions.
1091     // These methods are broadly value representation specific (i.e.
1092     // deal with the fact that a JSValue may be passed in one or two
1093     // machine registers, and delegate the calling convention specific
1094     // decision as to how to fill the regsiters to setupArguments* methods.
1095 #if USE(JSVALUE64)
1096     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, void* pointer)
1097     {
1098         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
1099         return appendCallWithExceptionCheckSetResult(operation, result);
1100     }
1101     JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
1102     {
1103         m_jit.setupArguments(arg1);
1104         JITCompiler::Call call = m_jit.appendCall(operation);
1105         m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
1106         return call;
1107     }
1108     JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
1109     {
1110         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1111         return appendCallWithExceptionCheckSetResult(operation, result);
1112     }
1113     JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg result, Identifier* identifier)
1114     {
1115         m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
1116         return appendCallWithExceptionCheckSetResult(operation, result);
1117     }
1118     JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg result, GPRReg arg1)
1119     {
1120         m_jit.setupArgumentsWithExecState(arg1);
1121         return appendCallWithExceptionCheckSetResult(operation, result);
1122     }
1123     JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
1124     {
1125         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
1126         return appendCallWithExceptionCheckSetResult(operation, result);
1127     }
1128     JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg result, int startConstant, int numConstants)
1129     {
1130         m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
1131         return appendCallWithExceptionCheckSetResult(operation, result);
1132     }
1133     JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, void* pointer)
1134     {
1135         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
1136         return appendCallWithExceptionCheckSetResult(operation, result);
1137     }
1138     JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
1139     {
1140         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1141         return appendCallWithExceptionCheckSetResult(operation, result);
1142     }
1143     JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
1144     {
1145         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1146         return appendCallWithExceptionCheckSetResult(operation, result);
1147     }
1148     JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1149     {
1150         m_jit.setupArgumentsWithExecState(arg1, arg2);
1151         return appendCallWithExceptionCheckSetResult(operation, result);
1152     }
1153     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, GPRReg arg1)
1154     {
1155         m_jit.setupArgumentsWithExecState(arg1);
1156         return appendCallWithExceptionCheckSetResult(operation, result);
1157     }
1158     JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
1159     {
1160         m_jit.setupArgumentsExecState();
1161         return appendCallWithExceptionCheckSetResult(operation, result);
1162     }
1163     JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
1164     {
1165         m_jit.setupArgumentsWithExecState(arg1);
1166         return appendCallWithExceptionCheckSetResult(operation, result);
1167     }
1168     JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell)
1169     {
1170         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
1171         return appendCallWithExceptionCheckSetResult(operation, result);
1172     }
1173     JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
1174     {
1175         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
1176         return appendCallWithExceptionCheckSetResult(operation, result);
1177     }
1178     JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
1179     {
1180         m_jit.setupArgumentsWithExecState(arg1);
1181         return appendCallWithExceptionCheckSetResult(operation, result);
1182     }
1183     JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1184     {
1185         m_jit.setupArgumentsWithExecState(arg1, arg2);
1186         return appendCallWithExceptionCheckSetResult(operation, result);
1187     }
1188     JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1189     {
1190         m_jit.setupArgumentsWithExecState(arg1, arg2);
1191         return appendCallWithExceptionCheckSetResult(operation, result);
1192     }
1193     JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1194     {
1195         m_jit.setupArgumentsWithExecState(arg1, arg2);
1196         return appendCallWithExceptionCheckSetResult(operation, result);
1197     }
1198     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, MacroAssembler::TrustedImm32 imm)
1199     {
1200         m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))));
1201         return appendCallWithExceptionCheckSetResult(operation, result);
1202     }
1203     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, MacroAssembler::TrustedImm32 imm, GPRReg arg2)
1204     {
1205         m_jit.setupArgumentsWithExecState(MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2);
1206         return appendCallWithExceptionCheckSetResult(operation, result);
1207     }
1208     JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1209     {
1210         m_jit.setupArgumentsWithExecState(arg1, arg2);
1211         return appendCallWithExceptionCheckSetResult(operation, result);
1212     }
1213     JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1214     {
1215         m_jit.setupArgumentsWithExecState(arg1, arg2);
1216         return appendCallWithExceptionCheckSetResult(operation, result);
1217     }
1218     JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1)
1219     {
1220         m_jit.setupArgumentsWithExecState(arg1);
1221         return appendCallWithExceptionCheck(operation);
1222     }
1223     JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer)
1224     {
1225         m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(pointer));
1226         return appendCallWithExceptionCheck(operation);
1227     }
1228     JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier)
1229     {
1230         m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(identifier));
1231         return appendCallWithExceptionCheck(operation);
1232     }
1233     JITCompiler::Call callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
1234     {
1235         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
1236         return appendCallWithExceptionCheck(operation);
1237     }
1238     JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
1239     {
1240         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
1241         return appendCallWithExceptionCheck(operation);
1242     }
1243     JITCompiler::Call callOperation(V_DFGOperation_EAZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
1244     {
1245         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
1246         return appendCallWithExceptionCheck(operation);
1247     }
1248     JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
1249     {
1250         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
1251         return appendCallWithExceptionCheck(operation);
1252     }
1253     JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1)
1254     {
1255         m_jit.setupArgumentsWithExecState(arg1);
1256         return appendCallWithExceptionCheckSetResult(operation, result);
1257     }
1258     JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
1259     {
1260         m_jit.setupArguments(arg1, arg2);
1261         return appendCallSetResult(operation, result);
1262     }
1263     JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
1264     {
1265         m_jit.setupArguments(arg1, arg2);
1266         return appendCallSetResult(operation, result);
1267     }
1268 #else
1269     JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
1270     {
1271         m_jit.setupArguments(arg1);
1272         JITCompiler::Call call = m_jit.appendCall(operation);
1273         m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
1274         return call;
1275     }
1276     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
1277     {
1278         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
1279         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1280     }
1281     JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, void* pointer)
1282     {
1283         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
1284         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1285     }
1286     JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
1287     {
1288         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1289         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1290     }
1291     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
1292     {
1293         m_jit.setupArgumentsWithExecState(arg1);
1294         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1295     }
1296     JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg resultTag, GPRReg resultPayload, Identifier* identifier)
1297     {
1298         m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
1299         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1300     }
1301     JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
1302     {
1303         m_jit.setupArgumentsWithExecState(arg1);
1304         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1305     }
1306     JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
1307     {
1308         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
1309         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1310     }
1311     JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg resultTag, GPRReg resultPayload, int startConstant, int numConstants)
1312     {
1313         m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
1314         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1315     }
1316     JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, void* pointer)
1317     {
1318         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(pointer));
1319         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1320     }
1321     JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
1322     {
1323         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
1324         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1325     }
1326     JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
1327     {
1328         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1329         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1330     }
1331     JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, Identifier* identifier)
1332     {
1333         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(identifier));
1334         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1335     }
1336     JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1Tag, GPRReg arg1Payload, Identifier* identifier)
1337     {
1338         m_jit.setupArgumentsWithExecState(arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
1339         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1340     }
1341     JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
1342     {
1343         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
1344         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1345     }
1346     JITCompiler::Call callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload)
1347     {
1348         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
1349         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1350     }
1351     JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
1352     {
1353         m_jit.setupArgumentsExecState();
1354         return appendCallWithExceptionCheckSetResult(operation, result);
1355     }
1356     JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
1357     {
1358         m_jit.setupArgumentsWithExecState(arg1);
1359         return appendCallWithExceptionCheckSetResult(operation, result);
1360     }
1361     JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell)
1362     {
1363         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
1364         return appendCallWithExceptionCheckSetResult(operation, result);
1365     }
1366     JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
1367     {
1368         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
1369         return appendCallWithExceptionCheckSetResult(operation, result);
1370     }
1371     JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
1372     {
1373         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
1374         return appendCallWithExceptionCheckSetResult(operation, result);
1375     }
1376     JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1377     {
1378         m_jit.setupArgumentsWithExecState(arg1, arg2);
1379         return appendCallWithExceptionCheckSetResult(operation, result);
1380     }
1381     JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
1382     {
1383         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
1384         return appendCallWithExceptionCheckSetResult(operation, result);
1385     }
1386     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
1387     {
1388         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
1389         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1390     }
1391     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::TrustedImm32 imm)
1392     {
1393         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, imm, TrustedImm32(JSValue::Int32Tag));
1394         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1395     }
1396     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, MacroAssembler::TrustedImm32 imm, GPRReg arg2Tag, GPRReg arg2Payload)
1397     {
1398         m_jit.setupArgumentsWithExecState(imm, TrustedImm32(JSValue::Int32Tag), arg2Payload, arg2Tag);
1399         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1400     }
1401     JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
1402     {
1403         m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
1404         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1405     }
1406     JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
1407     {
1408         m_jit.setupArgumentsWithExecState(arg1, arg2);
1409         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1410     }
1411     JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1)
1412     {
1413         m_jit.setupArgumentsWithExecState(arg1);
1414         return appendCallWithExceptionCheck(operation);
1415     }
1416     JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer)
1417     {
1418         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(pointer));
1419         return appendCallWithExceptionCheck(operation);
1420     }
1421     JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, Identifier* identifier)
1422     {
1423         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(identifier));
1424         return appendCallWithExceptionCheck(operation);
1425     }
1426     JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
1427     {
1428         m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
1429         return appendCallWithExceptionCheck(operation);
1430     }
1431     JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
1432     {
1433         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
1434         return appendCallWithExceptionCheck(operation);
1435     }
1436     JITCompiler::Call callOperation(V_DFGOperation_EAZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
1437     {
1438         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
1439         return appendCallWithExceptionCheck(operation);
1440     }
1441
1442     JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
1443     {
1444         m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
1445         return appendCallWithExceptionCheckSetResult(operation, result);
1446     }
1447
1448     JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
1449     {
1450         m_jit.setupArguments(arg1, arg2);
1451         return appendCallSetResult(operation, result);
1452     }
1453     JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
1454     {
1455         m_jit.setupArguments(arg1, arg2);
1456         return appendCallSetResult(operation, result);
1457     }
1458 #endif
1459
1460     // These methods add call instructions, with optional exception checks & setting results.
1461     JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
1462     {
1463         CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
1464         CallBeginToken token = m_jit.beginCall();
1465         JITCompiler::Call call = m_jit.appendCall(function);
1466         m_jit.addExceptionCheck(call, codeOrigin, token);
1467         return call;
1468     }
1469     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result)
1470     {
1471         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1472         m_jit.move(GPRInfo::returnValueGPR, result);
1473         return call;
1474     }
1475     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
1476     {
1477         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1478         m_jit.setupResults(result1, result2);
1479         return call;
1480     }
1481 #if CPU(X86)
1482     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
1483     {
1484         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1485         m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
1486         m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
1487         return call;
1488     }
1489     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
1490     {
1491         JITCompiler::Call call = m_jit.appendCall(function);
1492         m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
1493         m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
1494         return call;
1495     }
1496 #elif CPU(ARM)
1497     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
1498     {
1499         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1500         m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
1501         return call;
1502     }
1503     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
1504     {
1505         JITCompiler::Call call = m_jit.appendCall(function);
1506         m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
1507         return call;
1508     }
1509 #else
1510     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
1511     {
1512         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1513         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1514         return call;
1515     }
1516     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
1517     {
1518         JITCompiler::Call call = m_jit.appendCall(function);
1519         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1520         return call;
1521     }
1522 #endif
1523     
1524     void branchDouble(JITCompiler::DoubleCondition cond, FPRReg left, FPRReg right, BlockIndex destination)
1525     {
1526         if (!haveEdgeCodeToEmit(destination))
1527             return addBranch(m_jit.branchDouble(cond, left, right), destination);
1528         
1529         JITCompiler::Jump notTaken = m_jit.branchDouble(JITCompiler::invert(cond), left, right);
1530         emitEdgeCode(destination);
1531         addBranch(m_jit.jump(), destination);
1532         notTaken.link(&m_jit);
1533     }
1534     
1535     void branchDoubleNonZero(FPRReg value, FPRReg scratch, BlockIndex destination)
1536     {
1537         if (!haveEdgeCodeToEmit(destination))
1538             return addBranch(m_jit.branchDoubleNonZero(value, scratch), destination);
1539         
1540         JITCompiler::Jump notTaken = m_jit.branchDoubleZeroOrNaN(value, scratch);
1541         emitEdgeCode(destination);
1542         addBranch(m_jit.jump(), destination);
1543         notTaken.link(&m_jit);
1544     }
1545     
1546     template<typename T, typename U>
1547     void branch32(JITCompiler::RelationalCondition cond, T left, U right, BlockIndex destination)
1548     {
1549         if (!haveEdgeCodeToEmit(destination))
1550             return addBranch(m_jit.branch32(cond, left, right), destination);
1551         
1552         JITCompiler::Jump notTaken = m_jit.branch32(JITCompiler::invert(cond), left, right);
1553         emitEdgeCode(destination);
1554         addBranch(m_jit.jump(), destination);
1555         notTaken.link(&m_jit);
1556     }
1557     
1558     template<typename T, typename U>
1559     void branchTest32(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
1560     {
1561         ASSERT(JITCompiler::isInvertible(cond));
1562         
1563         if (!haveEdgeCodeToEmit(destination))
1564             return addBranch(m_jit.branchTest32(cond, value, mask), destination);
1565         
1566         JITCompiler::Jump notTaken = m_jit.branchTest32(JITCompiler::invert(cond), value, mask);
1567         emitEdgeCode(destination);
1568         addBranch(m_jit.jump(), destination);
1569         notTaken.link(&m_jit);
1570     }
1571     
1572     template<typename T>
1573     void branchTest32(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
1574     {
1575         ASSERT(JITCompiler::isInvertible(cond));
1576         
1577         if (!haveEdgeCodeToEmit(destination))
1578             return addBranch(m_jit.branchTest32(cond, value), destination);
1579         
1580         JITCompiler::Jump notTaken = m_jit.branchTest32(JITCompiler::invert(cond), value);
1581         emitEdgeCode(destination);
1582         addBranch(m_jit.jump(), destination);
1583         notTaken.link(&m_jit);
1584     }
1585     
1586     template<typename T, typename U>
1587     void branchPtr(JITCompiler::RelationalCondition cond, T left, U right, BlockIndex destination)
1588     {
1589         if (!haveEdgeCodeToEmit(destination))
1590             return addBranch(m_jit.branchPtr(cond, left, right), destination);
1591         
1592         JITCompiler::Jump notTaken = m_jit.branchPtr(JITCompiler::invert(cond), left, right);
1593         emitEdgeCode(destination);
1594         addBranch(m_jit.jump(), destination);
1595         notTaken.link(&m_jit);
1596     }
1597     
1598     template<typename T, typename U>
1599     void branchTestPtr(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
1600     {
1601         ASSERT(JITCompiler::isInvertible(cond));
1602         
1603         if (!haveEdgeCodeToEmit(destination))
1604             return addBranch(m_jit.branchTestPtr(cond, value, mask), destination);
1605         
1606         JITCompiler::Jump notTaken = m_jit.branchTestPtr(JITCompiler::invert(cond), value, mask);
1607         emitEdgeCode(destination);
1608         addBranch(m_jit.jump(), destination);
1609         notTaken.link(&m_jit);
1610     }
1611     
1612     template<typename T>
1613     void branchTestPtr(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
1614     {
1615         ASSERT(JITCompiler::isInvertible(cond));
1616         
1617         if (!haveEdgeCodeToEmit(destination))
1618             return addBranch(m_jit.branchTestPtr(cond, value), destination);
1619         
1620         JITCompiler::Jump notTaken = m_jit.branchTestPtr(JITCompiler::invert(cond), value);
1621         emitEdgeCode(destination);
1622         addBranch(m_jit.jump(), destination);
1623         notTaken.link(&m_jit);
1624     }
1625     
1626     template<typename T, typename U>
1627     void branchTest8(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
1628     {
1629         ASSERT(JITCompiler::isInvertible(cond));
1630         
1631         if (!haveEdgeCodeToEmit(destination))
1632             return addBranch(m_jit.branchTest8(cond, value, mask), destination);
1633         
1634         JITCompiler::Jump notTaken = m_jit.branchTest8(JITCompiler::invert(cond), value, mask);
1635         emitEdgeCode(destination);
1636         addBranch(m_jit.jump(), destination);
1637         notTaken.link(&m_jit);
1638     }
1639     
1640     template<typename T>
1641     void branchTest8(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
1642     {
1643         ASSERT(JITCompiler::isInvertible(cond));
1644         
1645         if (!haveEdgeCodeToEmit(destination))
1646             return addBranch(m_jit.branchTest8(cond, value), destination);
1647         
1648         JITCompiler::Jump notTaken = m_jit.branchTest8(JITCompiler::invert(cond), value);
1649         emitEdgeCode(destination);
1650         addBranch(m_jit.jump(), destination);
1651         notTaken.link(&m_jit);
1652     }
1653     
1654     enum FallThroughMode {
1655         AtFallThroughPoint,
1656         ForceJump
1657     };
1658     void jump(BlockIndex destination, FallThroughMode fallThroughMode = AtFallThroughPoint)
1659     {
1660         if (haveEdgeCodeToEmit(destination))
1661             emitEdgeCode(destination);
1662         if (destination == m_block + 1
1663             && fallThroughMode == AtFallThroughPoint)
1664             return;
1665         addBranch(m_jit.jump(), destination);
1666     }
1667     
1668     inline bool haveEdgeCodeToEmit(BlockIndex)
1669     {
1670         return DFG_ENABLE_EDGE_CODE_VERIFICATION;
1671     }
1672     void emitEdgeCode(BlockIndex destination)
1673     {
1674         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION)
1675             return;
1676         m_jit.move(TrustedImm32(destination), GPRInfo::regT0);
1677     }
1678
1679     void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination)
1680     {
1681         m_branches.append(BranchRecord(jump, destination));
1682     }
1683
1684     void linkBranches()
1685     {
1686         for (size_t i = 0; i < m_branches.size(); ++i) {
1687             BranchRecord& branch = m_branches[i];
1688             branch.jump.linkTo(m_blockHeads[branch.destination], &m_jit);
1689         }
1690     }
1691
1692     BasicBlock* block()
1693     {
1694         return m_jit.graph().m_blocks[m_block].get();
1695     }
1696
1697 #ifndef NDEBUG
1698     void dump(const char* label = 0);
1699 #endif
1700
1701 #if DFG_ENABLE(CONSISTENCY_CHECK)
1702     void checkConsistency();
1703 #else
1704     void checkConsistency() { }
1705 #endif
1706
1707     bool isInteger(NodeIndex nodeIndex)
1708     {
1709         Node& node = at(nodeIndex);
1710         if (node.hasInt32Result())
1711             return true;
1712
1713         if (isInt32Constant(nodeIndex))
1714             return true;
1715
1716         VirtualRegister virtualRegister = node.virtualRegister();
1717         GenerationInfo& info = m_generationInfo[virtualRegister];
1718         
1719         return info.isJSInteger();
1720     }
1721     
1722     bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
1723     bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
1724     void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
1725     void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
1726     void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
1727     void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker);
1728     void compileValueAdd(Node&);
1729     void compileObjectOrOtherLogicalNot(Edge value, const ClassInfo*, bool needSpeculationCheck);
1730     void compileLogicalNot(Node&);
1731     void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck);
1732     void emitBranch(Node&);
1733     
1734     void compileIntegerCompare(Node&, MacroAssembler::RelationalCondition);
1735     void compileDoubleCompare(Node&, MacroAssembler::DoubleCondition);
1736     
1737     bool compileStrictEqForConstant(Node&, Edge value, JSValue constant);
1738     
1739     bool compileStrictEq(Node&);
1740     
1741     void compileGetCharCodeAt(Node&);
1742     void compileGetByValOnString(Node&);
1743     void compileValueToInt32(Node&);
1744     void compileUInt32ToNumber(Node&);
1745     void compileInt32ToDouble(Node&);
1746     void compileGetByValOnByteArray(Node&);
1747     void compilePutByValForByteArray(GPRReg base, GPRReg property, Node&);
1748     void compileAdd(Node&);
1749     void compileArithSub(Node&);
1750     void compileArithNegate(Node&);
1751     void compileArithMul(Node&);
1752 #if CPU(X86) || CPU(X86_64)
1753     void compileIntegerArithDivForX86(Node&);
1754 #endif
1755     void compileArithMod(Node&);
1756     void compileSoftModulo(Node&);
1757     void compileGetTypedArrayLength(const TypedArrayDescriptor&, Node&, bool needsSpeculationCheck);
1758     enum TypedArraySpeculationRequirements {
1759         NoTypedArraySpecCheck,
1760         NoTypedArrayTypeSpecCheck,
1761         AllTypedArraySpecChecks
1762     };
1763     enum TypedArraySignedness {
1764         SignedTypedArray,
1765         UnsignedTypedArray
1766     };
1767     enum TypedArrayRounding {
1768         TruncateRounding,
1769         ClampRounding
1770     };
1771     void compileGetIndexedPropertyStorage(Node&);
1772     void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
1773     void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness, TypedArrayRounding = TruncateRounding);
1774     void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements);
1775     void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements);
1776     void compileNewFunctionNoCheck(Node&);
1777     void compileNewFunctionExpression(Node&);
1778     bool compileRegExpExec(Node&);
1779     
1780     template <typename ClassType, bool destructor, typename StructureType> 
1781     void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
1782     {
1783         MarkedAllocator* allocator = 0;
1784         if (destructor)
1785             allocator = &m_jit.globalData()->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
1786         else
1787             allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
1788
1789         m_jit.loadPtr(&allocator->m_firstFreeCell, resultGPR);
1790         slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
1791         
1792         // The object is half-allocated: we have what we know is a fresh object, but
1793         // it's still on the GC's free list.
1794         
1795         // Ditch the structure by placing it into the structure slot, so that we can reuse
1796         // scratchGPR.
1797         m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
1798         
1799         // Now that we have scratchGPR back, remove the object from the free list
1800         m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
1801         m_jit.storePtr(scratchGPR, &allocator->m_firstFreeCell);
1802         
1803         // Initialize the object's classInfo pointer
1804         m_jit.storePtr(MacroAssembler::TrustedImmPtr(&ClassType::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset()));
1805         
1806         // Initialize the object's inheritorID.
1807         m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
1808         
1809         // Initialize the object's property storage pointer.
1810         m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
1811         m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, ClassType::offsetOfPropertyStorage()));
1812     }
1813
1814     // It is acceptable to have structure be equal to scratch, so long as you're fine
1815     // with the structure GPR being clobbered.
1816     template<typename T>
1817     void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
1818     {
1819         return emitAllocateBasicJSObject<JSFinalObject, false>(structure, resultGPR, scratchGPR, slowPath);
1820     }
1821
1822 #if USE(JSVALUE64) 
1823     JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
1824 #elif USE(JSVALUE32_64)
1825     JITCompiler::Jump convertToDouble(JSValueOperand&, FPRReg result);
1826 #endif
1827
1828     // Add a speculation check without additional recovery.
1829     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail)
1830     {
1831         if (!m_compileOkay)
1832             return;
1833         m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this));
1834     }
1835     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
1836     {
1837         speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
1838     }
1839     // Add a set of speculation checks without additional recovery.
1840     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail)
1841     {
1842         Vector<MacroAssembler::Jump, 16> JumpVector = jumpsToFail.jumps();
1843         for (unsigned i = 0; i < JumpVector.size(); ++i)
1844             speculationCheck(kind, jsValueSource, nodeIndex, JumpVector[i]);
1845     }
1846     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail)
1847     {
1848         speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail);
1849     }
1850     // Add a speculation check with additional recovery.
1851     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
1852     {
1853         if (!m_compileOkay)
1854             return;
1855         m_jit.codeBlock()->appendSpeculationRecovery(recovery);
1856         m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_jit.codeBlock()->numberOfSpeculationRecoveries()));
1857     }
1858     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
1859     {
1860         speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery);
1861     }
1862     void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
1863     {
1864         speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
1865         
1866         Node& setLocal = at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock + 1));
1867         Node& nextNode = at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock + 2));
1868         ASSERT(setLocal.op() == SetLocal);
1869         ASSERT(setLocal.codeOrigin == at(m_compileIndex).codeOrigin);
1870         ASSERT(nextNode.codeOrigin != at(m_compileIndex).codeOrigin);
1871         
1872         OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
1873         exit.m_codeOrigin = nextNode.codeOrigin;
1874         exit.m_lastSetOperand = setLocal.local();
1875         
1876         exit.valueRecoveryForOperand(setLocal.local()) = valueRecovery;
1877     }
1878
1879     // Called when we statically determine that a speculation will fail.
1880     void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex)
1881     {
1882 #if DFG_ENABLE(DEBUG_VERBOSE)
1883         dataLog("SpeculativeJIT was terminated.\n");
1884 #endif
1885         if (!m_compileOkay)
1886             return;
1887         speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump());
1888         m_compileOkay = false;
1889     }
1890     void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
1891     {
1892         terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index());
1893     }
1894     
1895     template<bool strict>
1896     GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);
1897     
1898     // It is possible, during speculative generation, to reach a situation in which we
1899     // can statically determine a speculation will fail (for example, when two nodes
1900     // will make conflicting speculations about the same operand). In such cases this
1901     // flag is cleared, indicating no further code generation should take place.
1902     bool m_compileOkay;
1903     
1904     // Tracking for which nodes are currently holding the values of arguments and bytecode
1905     // operand-indexed variables.
1906     
1907     ValueSource valueSourceForOperand(int operand)
1908     {
1909         return valueSourceReferenceForOperand(operand);
1910     }
1911     
1912     void setNodeIndexForOperand(NodeIndex nodeIndex, int operand)
1913     {
1914         valueSourceReferenceForOperand(operand) = ValueSource(nodeIndex);
1915     }
1916     
1917     // Call this with care, since it both returns a reference into an array
1918     // and potentially resizes the array. So it would not be right to call this
1919     // twice and then perform operands on both references, since the one from
1920     // the first call may no longer be valid.
1921     ValueSource& valueSourceReferenceForOperand(int operand)
1922     {
1923         if (operandIsArgument(operand)) {
1924             int argument = operandToArgument(operand);
1925             return m_arguments[argument];
1926         }
1927         
1928         if ((unsigned)operand >= m_variables.size())
1929             m_variables.resize(operand + 1);
1930         
1931         return m_variables[operand];
1932     }
1933     
1934     // The JIT, while also provides MacroAssembler functionality.
1935     JITCompiler& m_jit;
1936     // The current node being generated.
1937     BlockIndex m_block;
1938     NodeIndex m_compileIndex;
1939     unsigned m_indexInBlock;
1940     // Virtual and physical register maps.
1941     Vector<GenerationInfo, 32> m_generationInfo;
1942     RegisterBank<GPRInfo> m_gprs;
1943     RegisterBank<FPRInfo> m_fprs;
1944
1945     Vector<MacroAssembler::Label> m_blockHeads;
1946     Vector<MacroAssembler::Label> m_osrEntryHeads;
1947     
1948     struct BranchRecord {
1949         BranchRecord(MacroAssembler::Jump jump, BlockIndex destination)
1950             : jump(jump)
1951             , destination(destination)
1952         {
1953         }
1954
1955         MacroAssembler::Jump jump;
1956         BlockIndex destination;
1957     };
1958     Vector<BranchRecord, 8> m_branches;
1959
1960     Vector<ValueSource, 0> m_arguments;
1961     Vector<ValueSource, 0> m_variables;
1962     int m_lastSetOperand;
1963     CodeOrigin m_codeOriginForOSR;
1964     
1965     AbstractState m_state;
1966     
1967     ValueRecovery computeValueRecoveryFor(const ValueSource&);
1968
1969     ValueRecovery computeValueRecoveryFor(int operand)
1970     {
1971         return computeValueRecoveryFor(valueSourceForOperand(operand));
1972     }
1973 };
1974
1975
1976 // === Operand types ===
1977 //
1978 // IntegerOperand, DoubleOperand and JSValueOperand.
1979 //
1980 // These classes are used to lock the operands to a node into machine
1981 // registers. These classes implement of pattern of locking a value
1982 // into register at the point of construction only if it is already in
1983 // registers, and otherwise loading it lazily at the point it is first
1984 // used. We do so in order to attempt to avoid spilling one operand
1985 // in order to make space available for another.
1986
1987 class IntegerOperand {
1988 public:
1989     explicit IntegerOperand(SpeculativeJIT* jit, Edge use)
1990         : m_jit(jit)
1991         , m_index(use.index())
1992         , m_gprOrInvalid(InvalidGPRReg)
1993 #ifndef NDEBUG
1994         , m_format(DataFormatNone)
1995 #endif
1996     {
1997         ASSERT(m_jit);
1998         ASSERT(use.useKind() != DoubleUse);
1999         if (jit->isFilled(m_index))
2000             gpr();
2001     }
2002
2003     ~IntegerOperand()
2004     {
2005         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2006         m_jit->unlock(m_gprOrInvalid);
2007     }
2008
2009     NodeIndex index() const
2010     {
2011         return m_index;
2012     }
2013
2014     DataFormat format()
2015     {
2016         gpr(); // m_format is set when m_gpr is locked.
2017         ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
2018         return m_format;
2019     }
2020
2021     GPRReg gpr()
2022     {
2023         if (m_gprOrInvalid == InvalidGPRReg)
2024             m_gprOrInvalid = m_jit->fillInteger(index(), m_format);
2025         return m_gprOrInvalid;
2026     }
2027     
2028     void use()
2029     {
2030         m_jit->use(m_index);
2031     }
2032
2033 private:
2034     SpeculativeJIT* m_jit;
2035     NodeIndex m_index;
2036     GPRReg m_gprOrInvalid;
2037     DataFormat m_format;
2038 };
2039
2040 class DoubleOperand {
2041 public:
2042     explicit DoubleOperand(SpeculativeJIT* jit, Edge use)
2043         : m_jit(jit)
2044         , m_index(use.index())
2045         , m_fprOrInvalid(InvalidFPRReg)
2046     {
2047         ASSERT(m_jit);
2048         
2049         // This is counter-intuitive but correct. DoubleOperand is intended to
2050         // be used only when you're a node that is happy to accept an untyped
2051         // value, but will special-case for doubles (using DoubleOperand) if the
2052         // value happened to already be represented as a double. The implication
2053         // is that you will not try to force the value to become a double if it
2054         // is not one already.
2055         ASSERT(use.useKind() != DoubleUse);
2056         
2057         if (jit->isFilledDouble(m_index))
2058             fpr();
2059     }
2060
2061     ~DoubleOperand()
2062     {
2063         ASSERT(m_fprOrInvalid != InvalidFPRReg);
2064         m_jit->unlock(m_fprOrInvalid);
2065     }
2066
2067     NodeIndex index() const
2068     {
2069         return m_index;
2070     }
2071
2072     FPRReg fpr()
2073     {
2074         if (m_fprOrInvalid == InvalidFPRReg)
2075             m_fprOrInvalid = m_jit->fillDouble(index());
2076         return m_fprOrInvalid;
2077     }
2078     
2079     void use()
2080     {
2081         m_jit->use(m_index);
2082     }
2083
2084 private:
2085     SpeculativeJIT* m_jit;
2086     NodeIndex m_index;
2087     FPRReg m_fprOrInvalid;
2088 };
2089
2090 class JSValueOperand {
2091 public:
2092     explicit JSValueOperand(SpeculativeJIT* jit, Edge use)
2093         : m_jit(jit)
2094         , m_index(use.index())
2095 #if USE(JSVALUE64)
2096         , m_gprOrInvalid(InvalidGPRReg)
2097 #elif USE(JSVALUE32_64)
2098         , m_isDouble(false)
2099 #endif
2100     {
2101         ASSERT(m_jit);
2102         ASSERT(use.useKind() != DoubleUse);
2103 #if USE(JSVALUE64)
2104         if (jit->isFilled(m_index))
2105             gpr();
2106 #elif USE(JSVALUE32_64)
2107         m_register.pair.tagGPR = InvalidGPRReg;
2108         m_register.pair.payloadGPR = InvalidGPRReg;
2109         if (jit->isFilled(m_index))
2110             fill();
2111 #endif
2112     }
2113
2114     ~JSValueOperand()
2115     {
2116 #if USE(JSVALUE64)
2117         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2118         m_jit->unlock(m_gprOrInvalid);
2119 #elif USE(JSVALUE32_64)
2120         if (m_isDouble) {
2121             ASSERT(m_register.fpr != InvalidFPRReg);
2122             m_jit->unlock(m_register.fpr);
2123         } else {
2124             ASSERT(m_register.pair.tagGPR != InvalidGPRReg && m_register.pair.payloadGPR != InvalidGPRReg);
2125             m_jit->unlock(m_register.pair.tagGPR);
2126             m_jit->unlock(m_register.pair.payloadGPR);
2127         }
2128 #endif
2129     }
2130
2131     NodeIndex index() const
2132     {
2133         return m_index;
2134     }
2135
2136 #if USE(JSVALUE64)
2137     GPRReg gpr()
2138     {
2139         if (m_gprOrInvalid == InvalidGPRReg)
2140             m_gprOrInvalid = m_jit->fillJSValue(index());
2141         return m_gprOrInvalid;
2142     }
2143     JSValueRegs jsValueRegs()
2144     {
2145         return JSValueRegs(gpr());
2146     }
2147 #elif USE(JSVALUE32_64)
2148     bool isDouble() { return m_isDouble; }
2149
2150     void fill()
2151     {
2152         if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg)
2153             m_isDouble = !m_jit->fillJSValue(index(), m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);
2154     }
2155
2156     GPRReg tagGPR()
2157     {
2158         fill();
2159         ASSERT(!m_isDouble);
2160         return m_register.pair.tagGPR;
2161     }
2162
2163     GPRReg payloadGPR()
2164     {
2165         fill();
2166         ASSERT(!m_isDouble);
2167         return m_register.pair.payloadGPR;
2168     }
2169
2170     JSValueRegs jsValueRegs()
2171     {
2172         return JSValueRegs(tagGPR(), payloadGPR());
2173     }
2174
2175     FPRReg fpr()
2176     {
2177         fill();
2178         ASSERT(m_isDouble);
2179         return m_register.fpr;
2180     }
2181 #endif
2182
2183     void use()
2184     {
2185         m_jit->use(m_index);
2186     }
2187
2188 private:
2189     SpeculativeJIT* m_jit;
2190     NodeIndex m_index;
2191 #if USE(JSVALUE64)
2192     GPRReg m_gprOrInvalid;
2193 #elif USE(JSVALUE32_64)
2194     union {
2195         struct {
2196             GPRReg tagGPR;
2197             GPRReg payloadGPR;
2198         } pair;
2199         FPRReg fpr;
2200     } m_register;
2201     bool m_isDouble;
2202 #endif
2203 };
2204
2205 class StorageOperand {
2206 public:
2207     explicit StorageOperand(SpeculativeJIT* jit, Edge use)
2208         : m_jit(jit)
2209         , m_index(use.index())
2210         , m_gprOrInvalid(InvalidGPRReg)
2211     {
2212         ASSERT(m_jit);
2213         ASSERT(use.useKind() != DoubleUse);
2214         if (jit->isFilled(m_index))
2215             gpr();
2216     }
2217     
2218     ~StorageOperand()
2219     {
2220         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2221         m_jit->unlock(m_gprOrInvalid);
2222     }
2223     
2224     NodeIndex index() const
2225     {
2226         return m_index;
2227     }
2228     
2229     GPRReg gpr()
2230     {
2231         if (m_gprOrInvalid == InvalidGPRReg)
2232             m_gprOrInvalid = m_jit->fillStorage(index());
2233         return m_gprOrInvalid;
2234     }
2235     
2236     void use()
2237     {
2238         m_jit->use(m_index);
2239     }
2240     
2241 private:
2242     SpeculativeJIT* m_jit;
2243     NodeIndex m_index;
2244     GPRReg m_gprOrInvalid;
2245 };
2246
2247
2248 // === Temporaries ===
2249 //
2250 // These classes are used to allocate temporary registers.
2251 // A mechanism is provided to attempt to reuse the registers
2252 // currently allocated to child nodes whose value is consumed
2253 // by, and not live after, this operation.
2254
2255 class GPRTemporary {
2256 public:
2257     GPRTemporary();
2258     GPRTemporary(SpeculativeJIT*);
2259     GPRTemporary(SpeculativeJIT*, GPRReg specific);
2260     GPRTemporary(SpeculativeJIT*, SpeculateIntegerOperand&);
2261     GPRTemporary(SpeculativeJIT*, SpeculateIntegerOperand&, SpeculateIntegerOperand&);
2262     GPRTemporary(SpeculativeJIT*, SpeculateStrictInt32Operand&);
2263     GPRTemporary(SpeculativeJIT*, IntegerOperand&);
2264     GPRTemporary(SpeculativeJIT*, IntegerOperand&, IntegerOperand&);
2265     GPRTemporary(SpeculativeJIT*, SpeculateCellOperand&);
2266     GPRTemporary(SpeculativeJIT*, SpeculateBooleanOperand&);
2267 #if USE(JSVALUE64)
2268     GPRTemporary(SpeculativeJIT*, JSValueOperand&);
2269 #elif USE(JSVALUE32_64)
2270     GPRTemporary(SpeculativeJIT*, JSValueOperand&, bool tag = true);
2271 #endif
2272     GPRTemporary(SpeculativeJIT*, StorageOperand&);
2273
2274     void adopt(GPRTemporary&);
2275
2276     ~GPRTemporary()
2277     {
2278         if (m_jit && m_gpr != InvalidGPRReg)
2279             m_jit->unlock(gpr());
2280     }
2281
2282     GPRReg gpr()
2283     {
2284         return m_gpr;
2285     }
2286
2287 private:
2288     SpeculativeJIT* m_jit;
2289     GPRReg m_gpr;
2290 };
2291
2292 class FPRTemporary {
2293 public:
2294     FPRTemporary(SpeculativeJIT*);
2295     FPRTemporary(SpeculativeJIT*, DoubleOperand&);
2296     FPRTemporary(SpeculativeJIT*, DoubleOperand&, DoubleOperand&);
2297     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&);
2298     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
2299 #if USE(JSVALUE32_64)
2300     FPRTemporary(SpeculativeJIT*, JSValueOperand&);
2301 #endif
2302
2303     ~FPRTemporary()
2304     {
2305         m_jit->unlock(fpr());
2306     }
2307
2308     FPRReg fpr() const
2309     {
2310         ASSERT(m_fpr != InvalidFPRReg);
2311         return m_fpr;
2312     }
2313
2314 protected:
2315     FPRTemporary(SpeculativeJIT* jit, FPRReg lockedFPR)
2316         : m_jit(jit)
2317         , m_fpr(lockedFPR)
2318     {
2319     }
2320
2321 private:
2322     SpeculativeJIT* m_jit;
2323     FPRReg m_fpr;
2324 };
2325
2326
2327 // === Results ===
2328 //
2329 // These classes lock the result of a call to a C++ helper function.
2330
2331 class GPRResult : public GPRTemporary {
2332 public:
2333     GPRResult(SpeculativeJIT* jit)
2334         : GPRTemporary(jit, GPRInfo::returnValueGPR)
2335     {
2336     }
2337 };
2338
2339 #if USE(JSVALUE32_64)
2340 class GPRResult2 : public GPRTemporary {
2341 public:
2342     GPRResult2(SpeculativeJIT* jit)
2343         : GPRTemporary(jit, GPRInfo::returnValueGPR2)
2344     {
2345     }
2346 };
2347 #endif
2348
2349 class FPRResult : public FPRTemporary {
2350 public:
2351     FPRResult(SpeculativeJIT* jit)
2352         : FPRTemporary(jit, lockedResult(jit))
2353     {
2354     }
2355
2356 private:
2357     static FPRReg lockedResult(SpeculativeJIT* jit)
2358     {
2359         jit->lock(FPRInfo::returnValueFPR);
2360         return FPRInfo::returnValueFPR;
2361     }
2362 };
2363
2364
2365 // === Speculative Operand types ===
2366 //
2367 // SpeculateIntegerOperand, SpeculateStrictInt32Operand and SpeculateCellOperand.
2368 //
2369 // These are used to lock the operands to a node into machine registers within the
2370 // SpeculativeJIT. The classes operate like those above, however these will
2371 // perform a speculative check for a more restrictive type than we can statically
2372 // determine the operand to have. If the operand does not have the requested type,
2373 // a bail-out to the non-speculative path will be taken.
2374
2375 class SpeculateIntegerOperand {
2376 public:
2377     explicit SpeculateIntegerOperand(SpeculativeJIT* jit, Edge use)
2378         : m_jit(jit)
2379         , m_index(use.index())
2380         , m_gprOrInvalid(InvalidGPRReg)
2381 #ifndef NDEBUG
2382         , m_format(DataFormatNone)
2383 #endif
2384     {
2385         ASSERT(m_jit);
2386         ASSERT(use.useKind() != DoubleUse);
2387         if (jit->isFilled(m_index))
2388             gpr();
2389     }
2390
2391     ~SpeculateIntegerOperand()
2392     {
2393         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2394         m_jit->unlock(m_gprOrInvalid);
2395     }
2396
2397     NodeIndex index() const
2398     {
2399         return m_index;
2400     }
2401
2402     DataFormat format()
2403     {
2404         gpr(); // m_format is set when m_gpr is locked.
2405         ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
2406         return m_format;
2407     }
2408
2409     GPRReg gpr()
2410     {
2411         if (m_gprOrInvalid == InvalidGPRReg)
2412             m_gprOrInvalid = m_jit->fillSpeculateInt(index(), m_format);
2413         return m_gprOrInvalid;
2414     }
2415
2416 private:
2417     SpeculativeJIT* m_jit;
2418     NodeIndex m_index;
2419     GPRReg m_gprOrInvalid;
2420     DataFormat m_format;
2421 };
2422
2423 class SpeculateStrictInt32Operand {
2424 public:
2425     explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge use)
2426         : m_jit(jit)
2427         , m_index(use.index())
2428         , m_gprOrInvalid(InvalidGPRReg)
2429     {
2430         ASSERT(m_jit);
2431         ASSERT(use.useKind() != DoubleUse);
2432         if (jit->isFilled(m_index))
2433             gpr();
2434     }
2435
2436     ~SpeculateStrictInt32Operand()
2437     {
2438         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2439         m_jit->unlock(m_gprOrInvalid);
2440     }
2441
2442     NodeIndex index() const
2443     {
2444         return m_index;
2445     }
2446
2447     GPRReg gpr()
2448     {
2449         if (m_gprOrInvalid == InvalidGPRReg)
2450             m_gprOrInvalid = m_jit->fillSpeculateIntStrict(index());
2451         return m_gprOrInvalid;
2452     }
2453     
2454     void use()
2455     {
2456         m_jit->use(m_index);
2457     }
2458
2459 private:
2460     SpeculativeJIT* m_jit;
2461     NodeIndex m_index;
2462     GPRReg m_gprOrInvalid;
2463 };
2464
2465 class SpeculateDoubleOperand {
2466 public:
2467     explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge use)
2468         : m_jit(jit)
2469         , m_index(use.index())
2470         , m_fprOrInvalid(InvalidFPRReg)
2471     {
2472         ASSERT(m_jit);
2473         ASSERT(use.useKind() == DoubleUse);
2474         if (jit->isFilled(m_index))
2475             fpr();
2476     }
2477
2478     ~SpeculateDoubleOperand()
2479     {
2480         ASSERT(m_fprOrInvalid != InvalidFPRReg);
2481         m_jit->unlock(m_fprOrInvalid);
2482     }
2483
2484     NodeIndex index() const
2485     {
2486         return m_index;
2487     }
2488
2489     FPRReg fpr()
2490     {
2491         if (m_fprOrInvalid == InvalidFPRReg)
2492             m_fprOrInvalid = m_jit->fillSpeculateDouble(index());
2493         return m_fprOrInvalid;
2494     }
2495
2496 private:
2497     SpeculativeJIT* m_jit;
2498     NodeIndex m_index;
2499     FPRReg m_fprOrInvalid;
2500 };
2501
2502 class SpeculateCellOperand {
2503 public:
2504     explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use)
2505         : m_jit(jit)
2506         , m_index(use.index())
2507         , m_gprOrInvalid(InvalidGPRReg)
2508     {
2509         ASSERT(m_jit);
2510         ASSERT(use.useKind() != DoubleUse);
2511         if (jit->isFilled(m_index))
2512             gpr();
2513     }
2514
2515     ~SpeculateCellOperand()
2516     {
2517         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2518         m_jit->unlock(m_gprOrInvalid);
2519     }
2520
2521     NodeIndex index() const
2522     {
2523         return m_index;
2524     }
2525
2526     GPRReg gpr()
2527     {
2528         if (m_gprOrInvalid == InvalidGPRReg)
2529             m_gprOrInvalid = m_jit->fillSpeculateCell(index());
2530         return m_gprOrInvalid;
2531     }
2532     
2533     void use()
2534     {
2535         m_jit->use(m_index);
2536     }
2537
2538 private:
2539     SpeculativeJIT* m_jit;
2540     NodeIndex m_index;
2541     GPRReg m_gprOrInvalid;
2542 };
2543
2544 class SpeculateBooleanOperand {
2545 public:
2546     explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge use)
2547         : m_jit(jit)
2548         , m_index(use.index())
2549         , m_gprOrInvalid(InvalidGPRReg)
2550     {
2551         ASSERT(m_jit);
2552         ASSERT(use.useKind() != DoubleUse);
2553         if (jit->isFilled(m_index))
2554             gpr();
2555     }
2556     
2557     ~SpeculateBooleanOperand()
2558     {
2559         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2560         m_jit->unlock(m_gprOrInvalid);
2561     }
2562     
2563     NodeIndex index() const
2564     {
2565         return m_index;
2566     }
2567     
2568     GPRReg gpr()
2569     {
2570         if (m_gprOrInvalid == InvalidGPRReg)
2571             m_gprOrInvalid = m_jit->fillSpeculateBoolean(index());
2572         return m_gprOrInvalid;
2573     }
2574     
2575     void use()
2576     {
2577         m_jit->use(m_index);
2578     }
2579
2580 private:
2581     SpeculativeJIT* m_jit;
2582     NodeIndex m_index;
2583     GPRReg m_gprOrInvalid;
2584 };
2585
2586 inline SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
2587     : m_compileOkay(true)
2588     , m_jit(jit)
2589     , m_compileIndex(0)
2590     , m_indexInBlock(0)
2591     , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
2592     , m_blockHeads(jit.graph().m_blocks.size())
2593     , m_arguments(jit.codeBlock()->numParameters())
2594     , m_variables(jit.graph().m_localVars)
2595     , m_lastSetOperand(std::numeric_limits<int>::max())
2596     , m_state(m_jit.graph())
2597 {
2598 }
2599
2600 } } // namespace JSC::DFG
2601
2602 #endif
2603 #endif
2604