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