74fe706f100d8dd96c99157307024fc5e59bfb46
[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     template<typename FunctionType, typename ArgumentType1>
1418     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
1419     {
1420         return callOperation(operation, arg1);
1421     }
1422     template<typename FunctionType, typename ArgumentType1, typename ArgumentType2>
1423     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2)
1424     {
1425         return callOperation(operation, arg1, arg2);
1426     }
1427     template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
1428     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3)
1429     {
1430         return callOperation(operation, arg1, arg2, arg3);
1431     }
1432     JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1)
1433     {
1434         m_jit.setupArgumentsWithExecState(arg1);
1435         return appendCallWithExceptionCheckSetResult(operation, result);
1436     }
1437     JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
1438     {
1439         m_jit.setupArguments(arg1, arg2);
1440         return appendCallSetResult(operation, result);
1441     }
1442     JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
1443     {
1444         m_jit.setupArguments(arg1, arg2);
1445         return appendCallSetResult(operation, result);
1446     }
1447 #else
1448
1449 // 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]).
1450 // To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary.
1451 #if COMPILER_SUPPORTS(EABI) && CPU(ARM)
1452 #define EABI_32BIT_DUMMY_ARG      TrustedImm32(0),
1453 #else
1454 #define EABI_32BIT_DUMMY_ARG
1455 #endif
1456
1457     JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
1458     {
1459         prepareForExternalCall();
1460         m_jit.setupArguments(arg1);
1461         JITCompiler::Call call = m_jit.appendCall(operation);
1462         m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
1463         return call;
1464     }
1465     JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg resultTag, GPRReg resultPayload)
1466     {
1467         m_jit.setupArgumentsExecState();
1468         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1469     }
1470     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
1471     {
1472         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
1473         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1474     }
1475     JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, void* pointer)
1476     {
1477         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
1478         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1479     }
1480     JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
1481     {
1482         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1483         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1484     }
1485     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
1486     {
1487         m_jit.setupArgumentsWithExecState(arg1);
1488         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1489     }
1490     JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg resultTag, GPRReg resultPayload, Identifier* identifier)
1491     {
1492         m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
1493         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1494     }
1495     JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
1496     {
1497         m_jit.setupArgumentsWithExecState(arg1);
1498         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1499     }
1500     JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
1501     {
1502         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
1503         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1504     }
1505     JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg resultTag, GPRReg resultPayload, int startConstant, int numConstants)
1506     {
1507         m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
1508         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1509     }
1510     JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, void* pointer)
1511     {
1512         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(pointer));
1513         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1514     }
1515     JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
1516     {
1517         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2);
1518         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1519     }
1520     JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
1521     {
1522         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
1523         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1524     }
1525     JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, Identifier* identifier)
1526     {
1527         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(identifier));
1528         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1529     }
1530     JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1Tag, GPRReg arg1Payload, Identifier* identifier)
1531     {
1532         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
1533         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1534     }
1535     JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
1536     {
1537         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2);
1538         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1539     }
1540     JITCompiler::Call callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload)
1541     {
1542         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
1543         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1544     }
1545     JITCompiler::Call callOperation(J_DFGOperation_EZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
1546     {
1547         m_jit.setupArgumentsWithExecState(arg1);
1548         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1549     }
1550     JITCompiler::Call callOperation(J_DFGOperation_EZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1)
1551     {
1552         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1));
1553         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1554     }
1555     JITCompiler::Call callOperation(J_DFGOperation_EZIcfZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
1556     {
1557         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2);
1558         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1559     }
1560     JITCompiler::Call callOperation(J_DFGOperation_EZZ operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1, GPRReg arg2)
1561     {
1562         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2);
1563         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1564     }
1565     JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
1566     {
1567         m_jit.setupArgumentsExecState();
1568         return appendCallWithExceptionCheckSetResult(operation, result);
1569     }
1570     JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
1571     {
1572         m_jit.setupArgumentsWithExecState(arg1);
1573         return appendCallWithExceptionCheckSetResult(operation, result);
1574     }
1575     JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell)
1576     {
1577         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
1578         return appendCallWithExceptionCheckSetResult(operation, result);
1579     }
1580     JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
1581     {
1582         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
1583         return appendCallWithExceptionCheckSetResult(operation, result);
1584     }
1585     JITCompiler::Call callOperation(C_DFGOperation_EIcf operation, GPRReg result, InlineCallFrame* inlineCallFrame)
1586     {
1587         m_jit.setupArgumentsWithExecState(TrustedImmPtr(inlineCallFrame));
1588         return appendCallWithExceptionCheckSetResult(operation, result);
1589     }
1590     JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
1591     {
1592         m_jit.setupArguments(arg1Payload, arg1Tag);
1593         return appendCallSetResult(operation, result);
1594     }
1595     JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
1596     {
1597         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
1598         return appendCallWithExceptionCheckSetResult(operation, result);
1599     }
1600     JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
1601     {
1602         m_jit.setupArgumentsWithExecState(arg1, arg2);
1603         return appendCallWithExceptionCheckSetResult(operation, result);
1604     }
1605     JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
1606     {
1607         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2Payload, arg2Tag);
1608         return appendCallWithExceptionCheckSetResult(operation, result);
1609     }
1610     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, 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, resultPayload, resultTag);
1614     }
1615     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::TrustedImm32 imm)
1616     {
1617         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, imm, TrustedImm32(JSValue::Int32Tag));
1618         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1619     }
1620     JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, MacroAssembler::TrustedImm32 imm, GPRReg arg2Tag, GPRReg arg2Payload)
1621     {
1622         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG imm, TrustedImm32(JSValue::Int32Tag), arg2Payload, arg2Tag);
1623         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1624     }
1625     JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
1626     {
1627         m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
1628         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1629     }
1630     JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
1631     {
1632         m_jit.setupArgumentsWithExecState(arg1, arg2);
1633         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
1634     }
1635     JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1)
1636     {
1637         m_jit.setupArgumentsWithExecState(arg1);
1638         return appendCallWithExceptionCheck(operation);
1639     }
1640     JITCompiler::Call callOperation(V_DFGOperation_ECIcf operation, GPRReg arg1, InlineCallFrame* inlineCallFrame)
1641     {
1642         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(inlineCallFrame));
1643         return appendCallWithExceptionCheck(operation);
1644     }
1645     JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer)
1646     {
1647         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2, TrustedImmPtr(pointer));
1648         return appendCallWithExceptionCheck(operation);
1649     }
1650     JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, Identifier* identifier)
1651     {
1652         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2, TrustedImmPtr(identifier));
1653         return appendCallWithExceptionCheck(operation);
1654     }
1655     JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
1656     {
1657         m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
1658         return appendCallWithExceptionCheck(operation);
1659     }
1660     JITCompiler::Call callOperation(V_DFGOperation_ECZ operation, GPRReg arg1, int arg2)
1661     {
1662         m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2));
1663         return appendCallWithExceptionCheck(operation);
1664     }
1665     JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
1666     {
1667         m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
1668         return appendCallWithExceptionCheck(operation);
1669     }
1670     JITCompiler::Call callOperation(V_DFGOperation_EAZJ 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     template<typename FunctionType, typename ArgumentType1>
1676     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
1677     {
1678         return callOperation(operation, arg1);
1679     }
1680     template<typename FunctionType, typename ArgumentType1, typename ArgumentType2>
1681     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2)
1682     {
1683         return callOperation(operation, arg1, arg2);
1684     }
1685     template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3, typename ArgumentType4>
1686     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3, ArgumentType4 arg4)
1687     {
1688         return callOperation(operation, arg1, arg2, arg3, arg4);
1689     }
1690     template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3, typename ArgumentType4, typename ArgumentType5>
1691     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3, ArgumentType4 arg4, ArgumentType5 arg5)
1692     {
1693         return callOperation(operation, arg1, arg2, arg3, arg4, arg5);
1694     }
1695
1696     JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
1697     {
1698         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
1699         return appendCallWithExceptionCheckSetResult(operation, result);
1700     }
1701
1702     JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
1703     {
1704         m_jit.setupArguments(arg1, arg2);
1705         return appendCallSetResult(operation, result);
1706     }
1707     JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
1708     {
1709         m_jit.setupArguments(arg1, arg2);
1710         return appendCallSetResult(operation, result);
1711     }
1712
1713 #undef EABI_32BIT_DUMMY_ARG
1714     
1715     template<typename FunctionType>
1716     JITCompiler::Call callOperation(
1717         FunctionType operation, JSValueRegs result)
1718     {
1719         return callOperation(operation, result.tagGPR(), result.payloadGPR());
1720     }
1721     template<typename FunctionType, typename ArgumentType1>
1722     JITCompiler::Call callOperation(
1723         FunctionType operation, JSValueRegs result, ArgumentType1 arg1)
1724     {
1725         return callOperation(operation, result.tagGPR(), result.payloadGPR(), arg1);
1726     }
1727     template<typename FunctionType, typename ArgumentType1, typename ArgumentType2>
1728     JITCompiler::Call callOperation(
1729         FunctionType operation, JSValueRegs result, ArgumentType1 arg1, ArgumentType2 arg2)
1730     {
1731         return callOperation(operation, result.tagGPR(), result.payloadGPR(), arg1, arg2);
1732     }
1733     template<
1734         typename FunctionType, typename ArgumentType1, typename ArgumentType2,
1735         typename ArgumentType3>
1736     JITCompiler::Call callOperation(
1737         FunctionType operation, JSValueRegs result, ArgumentType1 arg1, ArgumentType2 arg2,
1738         ArgumentType3 arg3)
1739     {
1740         return callOperation(operation, result.tagGPR(), result.payloadGPR(), arg1, arg2, arg3);
1741     }
1742     template<
1743         typename FunctionType, typename ArgumentType1, typename ArgumentType2,
1744         typename ArgumentType3, typename ArgumentType4>
1745     JITCompiler::Call callOperation(
1746         FunctionType operation, JSValueRegs result, ArgumentType1 arg1, ArgumentType2 arg2,
1747         ArgumentType3 arg3, ArgumentType4 arg4)
1748     {
1749         return callOperation(operation, result.tagGPR(), result.payloadGPR(), arg1, arg2, arg3, arg4);
1750     }
1751     template<
1752         typename FunctionType, typename ArgumentType1, typename ArgumentType2,
1753         typename ArgumentType3, typename ArgumentType4, typename ArgumentType5>
1754     JITCompiler::Call callOperation(
1755         FunctionType operation, JSValueRegs result, ArgumentType1 arg1, ArgumentType2 arg2,
1756         ArgumentType3 arg3, ArgumentType4 arg4, ArgumentType5 arg5)
1757     {
1758         return callOperation(
1759             operation, result.tagGPR(), result.payloadGPR(), arg1, arg2, arg3, arg4, arg5);
1760     }
1761 #endif
1762     
1763 #if !defined(NDEBUG) && !CPU(ARM_THUMB2)
1764     void prepareForExternalCall()
1765     {
1766         for (unsigned i = 0; i < sizeof(void*) / 4; i++)
1767             m_jit.store32(TrustedImm32(0xbadbeef), reinterpret_cast<char*>(&m_jit.globalData()->topCallFrame) + i * 4);
1768     }
1769 #else
1770     void prepareForExternalCall() { }
1771 #endif
1772
1773     // These methods add call instructions, with optional exception checks & setting results.
1774     JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
1775     {
1776         prepareForExternalCall();
1777         CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
1778         CallBeginToken token = m_jit.beginCall();
1779         JITCompiler::Call call = m_jit.appendCall(function);
1780         m_jit.addExceptionCheck(call, codeOrigin, token);
1781         return call;
1782     }
1783     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result)
1784     {
1785         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1786         m_jit.move(GPRInfo::returnValueGPR, result);
1787         return call;
1788     }
1789     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, GPRReg result)
1790     {
1791         prepareForExternalCall();
1792         JITCompiler::Call call = m_jit.appendCall(function);
1793         m_jit.move(GPRInfo::returnValueGPR, result);
1794         return call;
1795     }
1796     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
1797     {
1798         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1799         m_jit.setupResults(result1, result2);
1800         return call;
1801     }
1802 #if CPU(X86)
1803     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
1804     {
1805         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1806         m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
1807         m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
1808         return call;
1809     }
1810     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
1811     {
1812         JITCompiler::Call call = m_jit.appendCall(function);
1813         m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
1814         m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
1815         return call;
1816     }
1817 #elif CPU(ARM)
1818     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
1819     {
1820         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1821         m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
1822         return call;
1823     }
1824     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
1825     {
1826         JITCompiler::Call call = m_jit.appendCall(function);
1827         m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
1828         return call;
1829     }
1830 #else
1831     JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
1832     {
1833         JITCompiler::Call call = appendCallWithExceptionCheck(function);
1834         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1835         return call;
1836     }
1837     JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
1838     {
1839         JITCompiler::Call call = m_jit.appendCall(function);
1840         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1841         return call;
1842     }
1843 #endif
1844     
1845     void branchDouble(JITCompiler::DoubleCondition cond, FPRReg left, FPRReg right, BlockIndex destination)
1846     {
1847         if (!haveEdgeCodeToEmit(destination))
1848             return addBranch(m_jit.branchDouble(cond, left, right), destination);
1849         
1850         JITCompiler::Jump notTaken = m_jit.branchDouble(JITCompiler::invert(cond), left, right);
1851         emitEdgeCode(destination);
1852         addBranch(m_jit.jump(), destination);
1853         notTaken.link(&m_jit);
1854     }
1855     
1856     void branchDoubleNonZero(FPRReg value, FPRReg scratch, BlockIndex destination)
1857     {
1858         if (!haveEdgeCodeToEmit(destination))
1859             return addBranch(m_jit.branchDoubleNonZero(value, scratch), destination);
1860         
1861         JITCompiler::Jump notTaken = m_jit.branchDoubleZeroOrNaN(value, scratch);
1862         emitEdgeCode(destination);
1863         addBranch(m_jit.jump(), destination);
1864         notTaken.link(&m_jit);
1865     }
1866     
1867     template<typename T, typename U>
1868     void branch32(JITCompiler::RelationalCondition cond, T left, U right, BlockIndex destination)
1869     {
1870         if (!haveEdgeCodeToEmit(destination))
1871             return addBranch(m_jit.branch32(cond, left, right), destination);
1872         
1873         JITCompiler::Jump notTaken = m_jit.branch32(JITCompiler::invert(cond), left, right);
1874         emitEdgeCode(destination);
1875         addBranch(m_jit.jump(), destination);
1876         notTaken.link(&m_jit);
1877     }
1878     
1879     template<typename T, typename U>
1880     void branchTest32(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
1881     {
1882         ASSERT(JITCompiler::isInvertible(cond));
1883         
1884         if (!haveEdgeCodeToEmit(destination))
1885             return addBranch(m_jit.branchTest32(cond, value, mask), destination);
1886         
1887         JITCompiler::Jump notTaken = m_jit.branchTest32(JITCompiler::invert(cond), value, mask);
1888         emitEdgeCode(destination);
1889         addBranch(m_jit.jump(), destination);
1890         notTaken.link(&m_jit);
1891     }
1892     
1893     template<typename T>
1894     void branchTest32(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
1895     {
1896         ASSERT(JITCompiler::isInvertible(cond));
1897         
1898         if (!haveEdgeCodeToEmit(destination))
1899             return addBranch(m_jit.branchTest32(cond, value), destination);
1900         
1901         JITCompiler::Jump notTaken = m_jit.branchTest32(JITCompiler::invert(cond), value);
1902         emitEdgeCode(destination);
1903         addBranch(m_jit.jump(), destination);
1904         notTaken.link(&m_jit);
1905     }
1906     
1907     template<typename T, typename U>
1908     void branchPtr(JITCompiler::RelationalCondition cond, T left, U right, BlockIndex destination)
1909     {
1910         if (!haveEdgeCodeToEmit(destination))
1911             return addBranch(m_jit.branchPtr(cond, left, right), destination);
1912         
1913         JITCompiler::Jump notTaken = m_jit.branchPtr(JITCompiler::invert(cond), left, right);
1914         emitEdgeCode(destination);
1915         addBranch(m_jit.jump(), destination);
1916         notTaken.link(&m_jit);
1917     }
1918     
1919     template<typename T, typename U>
1920     void branchTestPtr(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
1921     {
1922         ASSERT(JITCompiler::isInvertible(cond));
1923         
1924         if (!haveEdgeCodeToEmit(destination))
1925             return addBranch(m_jit.branchTestPtr(cond, value, mask), destination);
1926         
1927         JITCompiler::Jump notTaken = m_jit.branchTestPtr(JITCompiler::invert(cond), value, mask);
1928         emitEdgeCode(destination);
1929         addBranch(m_jit.jump(), destination);
1930         notTaken.link(&m_jit);
1931     }
1932     
1933     template<typename T>
1934     void branchTestPtr(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
1935     {
1936         ASSERT(JITCompiler::isInvertible(cond));
1937         
1938         if (!haveEdgeCodeToEmit(destination))
1939             return addBranch(m_jit.branchTestPtr(cond, value), destination);
1940         
1941         JITCompiler::Jump notTaken = m_jit.branchTestPtr(JITCompiler::invert(cond), value);
1942         emitEdgeCode(destination);
1943         addBranch(m_jit.jump(), destination);
1944         notTaken.link(&m_jit);
1945     }
1946     
1947     template<typename T, typename U>
1948     void branchTest8(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
1949     {
1950         ASSERT(JITCompiler::isInvertible(cond));
1951         
1952         if (!haveEdgeCodeToEmit(destination))
1953             return addBranch(m_jit.branchTest8(cond, value, mask), destination);
1954         
1955         JITCompiler::Jump notTaken = m_jit.branchTest8(JITCompiler::invert(cond), value, mask);
1956         emitEdgeCode(destination);
1957         addBranch(m_jit.jump(), destination);
1958         notTaken.link(&m_jit);
1959     }
1960     
1961     template<typename T>
1962     void branchTest8(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
1963     {
1964         ASSERT(JITCompiler::isInvertible(cond));
1965         
1966         if (!haveEdgeCodeToEmit(destination))
1967             return addBranch(m_jit.branchTest8(cond, value), destination);
1968         
1969         JITCompiler::Jump notTaken = m_jit.branchTest8(JITCompiler::invert(cond), value);
1970         emitEdgeCode(destination);
1971         addBranch(m_jit.jump(), destination);
1972         notTaken.link(&m_jit);
1973     }
1974     
1975     enum FallThroughMode {
1976         AtFallThroughPoint,
1977         ForceJump
1978     };
1979     void jump(BlockIndex destination, FallThroughMode fallThroughMode = AtFallThroughPoint)
1980     {
1981         if (haveEdgeCodeToEmit(destination))
1982             emitEdgeCode(destination);
1983         if (destination == nextBlock()
1984             && fallThroughMode == AtFallThroughPoint)
1985             return;
1986         addBranch(m_jit.jump(), destination);
1987     }
1988     
1989     inline bool haveEdgeCodeToEmit(BlockIndex)
1990     {
1991         return DFG_ENABLE_EDGE_CODE_VERIFICATION;
1992     }
1993     void emitEdgeCode(BlockIndex destination)
1994     {
1995         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION)
1996             return;
1997         m_jit.move(TrustedImm32(destination), GPRInfo::regT0);
1998     }
1999
2000     void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination)
2001     {
2002         m_branches.append(BranchRecord(jump, destination));
2003     }
2004
2005     void linkBranches()
2006     {
2007         for (size_t i = 0; i < m_branches.size(); ++i) {
2008             BranchRecord& branch = m_branches[i];
2009             branch.jump.linkTo(m_blockHeads[branch.destination], &m_jit);
2010         }
2011     }
2012
2013     BasicBlock* block()
2014     {
2015         return m_jit.graph().m_blocks[m_block].get();
2016     }
2017
2018 #ifndef NDEBUG
2019     void dump(const char* label = 0);
2020 #endif
2021
2022 #if DFG_ENABLE(CONSISTENCY_CHECK)
2023     void checkConsistency();
2024 #else
2025     void checkConsistency() { }
2026 #endif
2027
2028     bool isInteger(NodeIndex nodeIndex)
2029     {
2030         Node& node = at(nodeIndex);
2031         if (node.hasInt32Result())
2032             return true;
2033
2034         if (isInt32Constant(nodeIndex))
2035             return true;
2036
2037         VirtualRegister virtualRegister = node.virtualRegister();
2038         GenerationInfo& info = m_generationInfo[virtualRegister];
2039         
2040         return info.isJSInteger();
2041     }
2042     
2043     bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
2044     bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
2045     void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
2046     void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
2047     void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, SpeculatedTypeChecker);
2048     void compilePeepHoleObjectToObjectOrOtherEquality(
2049         Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, SpeculatedTypeChecker);
2050     void compileObjectEquality(Node&, const ClassInfo*, SpeculatedTypeChecker);
2051     void compileObjectToObjectOrOtherEquality(
2052         Edge leftChild, Edge rightChild, const ClassInfo*, SpeculatedTypeChecker);
2053     void compileValueAdd(Node&);
2054     void compileObjectOrOtherLogicalNot(Edge value, const ClassInfo*, bool needSpeculationCheck);
2055     void compileLogicalNot(Node&);
2056     void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck);
2057     void emitBranch(Node&);
2058     
2059     void compileIntegerCompare(Node&, MacroAssembler::RelationalCondition);
2060     void compileDoubleCompare(Node&, MacroAssembler::DoubleCondition);
2061     
2062     bool compileStrictEqForConstant(Node&, Edge value, JSValue constant);
2063     
2064     bool compileStrictEq(Node&);
2065     
2066     void compileGetCharCodeAt(Node&);
2067     void compileGetByValOnString(Node&);
2068
2069     void compileGetByValOnArguments(Node&);
2070     void compileGetArgumentsLength(Node&);
2071     
2072     void compileValueToInt32(Node&);
2073     void compileUInt32ToNumber(Node&);
2074     void compileDoubleAsInt32(Node&);
2075     void compileInt32ToDouble(Node&);
2076     void compileAdd(Node&);
2077     void compileArithSub(Node&);
2078     void compileArithNegate(Node&);
2079     void compileArithMul(Node&);
2080 #if CPU(X86) || CPU(X86_64)
2081     void compileIntegerArithDivForX86(Node&);
2082 #endif
2083     void compileArithMod(Node&);
2084     void compileSoftModulo(Node&);
2085     void compileGetTypedArrayLength(const TypedArrayDescriptor&, Node&, bool needsSpeculationCheck);
2086     enum TypedArraySpeculationRequirements {
2087         NoTypedArraySpecCheck,
2088         NoTypedArrayTypeSpecCheck,
2089         AllTypedArraySpecChecks
2090     };
2091     enum TypedArraySignedness {
2092         SignedTypedArray,
2093         UnsignedTypedArray
2094     };
2095     enum TypedArrayRounding {
2096         TruncateRounding,
2097         ClampRounding
2098     };
2099     void compileGetIndexedPropertyStorage(Node&);
2100     void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
2101     void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness, TypedArrayRounding = TruncateRounding);
2102     void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements);
2103     void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements);
2104     void compileNewFunctionNoCheck(Node&);
2105     void compileNewFunctionExpression(Node&);
2106     bool compileRegExpExec(Node&);
2107     
2108     template <typename ClassType, bool destructor, typename StructureType> 
2109     void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
2110     {
2111         MarkedAllocator* allocator = 0;
2112         if (destructor)
2113             allocator = &m_jit.globalData()->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
2114         else
2115             allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
2116
2117         m_jit.loadPtr(&allocator->m_freeList.head, resultGPR);
2118         slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
2119         
2120         // The object is half-allocated: we have what we know is a fresh object, but
2121         // it's still on the GC's free list.
2122         
2123         // Ditch the structure by placing it into the structure slot, so that we can reuse
2124         // scratchGPR.
2125         m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
2126         
2127         // Now that we have scratchGPR back, remove the object from the free list
2128         m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
2129         m_jit.storePtr(scratchGPR, &allocator->m_freeList.head);
2130         
2131         // Initialize the object's classInfo pointer
2132         m_jit.storePtr(MacroAssembler::TrustedImmPtr(&ClassType::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset()));
2133         
2134         // Initialize the object's inheritorID.
2135         m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
2136         
2137         // Initialize the object's property storage pointer.
2138         m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
2139         m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, ClassType::offsetOfPropertyStorage()));
2140     }
2141
2142     // It is acceptable to have structure be equal to scratch, so long as you're fine
2143     // with the structure GPR being clobbered.
2144     template<typename T>
2145     void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
2146     {
2147         return emitAllocateBasicJSObject<JSFinalObject, false>(structure, resultGPR, scratchGPR, slowPath);
2148     }
2149
2150 #if USE(JSVALUE64) 
2151     JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
2152 #elif USE(JSVALUE32_64)
2153     JITCompiler::Jump convertToDouble(JSValueOperand&, FPRReg result);
2154 #endif
2155
2156     // Add a speculation check without additional recovery.
2157     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail)
2158     {
2159         if (!m_compileOkay)
2160             return;
2161         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2162         m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this));
2163     }
2164     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
2165     {
2166         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2167         speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
2168     }
2169     // Add a set of speculation checks without additional recovery.
2170     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail)
2171     {
2172         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2173         Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
2174         for (unsigned i = 0; i < jumpVector.size(); ++i)
2175             speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]);
2176     }
2177     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail)
2178     {
2179         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2180         speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail);
2181     }
2182     // Add a speculation check with additional recovery.
2183     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
2184     {
2185         if (!m_compileOkay)
2186             return;
2187         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2188         m_jit.codeBlock()->appendSpeculationRecovery(recovery);
2189         m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_jit.codeBlock()->numberOfSpeculationRecoveries()));
2190     }
2191     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
2192     {
2193         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2194         speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery);
2195     }
2196     void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
2197     {
2198         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2199         speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
2200         
2201         unsigned setLocalIndexInBlock = m_indexInBlock + 1;
2202         
2203         Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock));
2204         bool hadInt32ToDouble = false;
2205         
2206         if (setLocal->op() == Int32ToDouble) {
2207             setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
2208             hadInt32ToDouble = true;
2209         }
2210         if (setLocal->op() == Flush || setLocal->op() == Phantom)
2211             setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
2212         
2213         if (hadInt32ToDouble)
2214             ASSERT(at(setLocal->child1()).child1() == m_compileIndex);
2215         else
2216             ASSERT(setLocal->child1() == m_compileIndex);
2217         ASSERT(setLocal->op() == SetLocal);
2218         ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin);
2219
2220         Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));
2221         ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin);
2222         
2223         OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
2224         exit.m_codeOrigin = nextNode->codeOrigin;
2225         exit.m_lastSetOperand = setLocal->local();
2226         
2227         exit.valueRecoveryForOperand(setLocal->local()) = valueRecovery;
2228     }
2229     void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
2230     {
2231         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2232         Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
2233         for (unsigned i = 0; i < jumpVector.size(); ++i)
2234             forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery);
2235     }
2236
2237     // Called when we statically determine that a speculation will fail.
2238     void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex)
2239     {
2240         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2241 #if DFG_ENABLE(DEBUG_VERBOSE)
2242         dataLog("SpeculativeJIT was terminated.\n");
2243 #endif
2244         if (!m_compileOkay)
2245             return;
2246         speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump());
2247         m_compileOkay = false;
2248     }
2249     void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
2250     {
2251         ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
2252         terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index());
2253     }
2254     
2255     template<bool strict>
2256     GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);
2257     
2258     // It is possible, during speculative generation, to reach a situation in which we
2259     // can statically determine a speculation will fail (for example, when two nodes
2260     // will make conflicting speculations about the same operand). In such cases this
2261     // flag is cleared, indicating no further code generation should take place.
2262     bool m_compileOkay;
2263     
2264     // Tracking for which nodes are currently holding the values of arguments and bytecode
2265     // operand-indexed variables.
2266     
2267     ValueSource valueSourceForOperand(int operand)
2268     {
2269         return valueSourceReferenceForOperand(operand);
2270     }
2271     
2272     void setNodeIndexForOperand(NodeIndex nodeIndex, int operand)
2273     {
2274         valueSourceReferenceForOperand(operand) = ValueSource(nodeIndex);
2275     }
2276     
2277     // Call this with care, since it both returns a reference into an array
2278     // and potentially resizes the array. So it would not be right to call this
2279     // twice and then perform operands on both references, since the one from
2280     // the first call may no longer be valid.
2281     ValueSource& valueSourceReferenceForOperand(int operand)
2282     {
2283         if (operandIsArgument(operand)) {
2284             int argument = operandToArgument(operand);
2285             return m_arguments[argument];
2286         }
2287         
2288         if ((unsigned)operand >= m_variables.size())
2289             m_variables.resize(operand + 1);
2290         
2291         return m_variables[operand];
2292     }
2293     
2294     JITCompiler& m_jit;
2295
2296     // The current node being generated.
2297     BlockIndex m_block;
2298     NodeIndex m_compileIndex;
2299     unsigned m_indexInBlock;
2300     // Virtual and physical register maps.
2301     Vector<GenerationInfo, 32> m_generationInfo;
2302     RegisterBank<GPRInfo> m_gprs;
2303     RegisterBank<FPRInfo> m_fprs;
2304
2305     Vector<MacroAssembler::Label> m_blockHeads;
2306     Vector<MacroAssembler::Label> m_osrEntryHeads;
2307     
2308     struct BranchRecord {
2309         BranchRecord(MacroAssembler::Jump jump, BlockIndex destination)
2310             : jump(jump)
2311             , destination(destination)
2312         {
2313         }
2314
2315         MacroAssembler::Jump jump;
2316         BlockIndex destination;
2317     };
2318     Vector<BranchRecord, 8> m_branches;
2319
2320     Vector<ValueSource, 0> m_arguments;
2321     Vector<ValueSource, 0> m_variables;
2322     int m_lastSetOperand;
2323     CodeOrigin m_codeOriginForOSR;
2324     
2325     AbstractState m_state;
2326     
2327     bool m_isCheckingArgumentTypes;
2328     
2329     Vector<SlowPathGenerator*, 8> m_slowPathGenerators; // doesn't use OwnPtr<> because I don't want to include DFGSlowPathGenerator.h
2330     Vector<SilentRegisterSavePlan> m_plans;
2331
2332     ValueRecovery computeValueRecoveryFor(const ValueSource&);
2333
2334     ValueRecovery computeValueRecoveryFor(int operand)
2335     {
2336         return computeValueRecoveryFor(valueSourceForOperand(operand));
2337     }
2338 };
2339
2340
2341 // === Operand types ===
2342 //
2343 // IntegerOperand, DoubleOperand and JSValueOperand.
2344 //
2345 // These classes are used to lock the operands to a node into machine
2346 // registers. These classes implement of pattern of locking a value
2347 // into register at the point of construction only if it is already in
2348 // registers, and otherwise loading it lazily at the point it is first
2349 // used. We do so in order to attempt to avoid spilling one operand
2350 // in order to make space available for another.
2351
2352 class IntegerOperand {
2353 public:
2354     explicit IntegerOperand(SpeculativeJIT* jit, Edge use)
2355         : m_jit(jit)
2356         , m_index(use.index())
2357         , m_gprOrInvalid(InvalidGPRReg)
2358 #ifndef NDEBUG
2359         , m_format(DataFormatNone)
2360 #endif
2361     {
2362         ASSERT(m_jit);
2363         ASSERT(use.useKind() != DoubleUse);
2364         if (jit->isFilled(m_index))
2365             gpr();
2366     }
2367
2368     ~IntegerOperand()
2369     {
2370         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2371         m_jit->unlock(m_gprOrInvalid);
2372     }
2373
2374     NodeIndex index() const
2375     {
2376         return m_index;
2377     }
2378
2379     DataFormat format()
2380     {
2381         gpr(); // m_format is set when m_gpr is locked.
2382         ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
2383         return m_format;
2384     }
2385
2386     GPRReg gpr()
2387     {
2388         if (m_gprOrInvalid == InvalidGPRReg)
2389             m_gprOrInvalid = m_jit->fillInteger(index(), m_format);
2390         return m_gprOrInvalid;
2391     }
2392     
2393     void use()
2394     {
2395         m_jit->use(m_index);
2396     }
2397
2398 private:
2399     SpeculativeJIT* m_jit;
2400     NodeIndex m_index;
2401     GPRReg m_gprOrInvalid;
2402     DataFormat m_format;
2403 };
2404
2405 class DoubleOperand {
2406 public:
2407     explicit DoubleOperand(SpeculativeJIT* jit, Edge use)
2408         : m_jit(jit)
2409         , m_index(use.index())
2410         , m_fprOrInvalid(InvalidFPRReg)
2411     {
2412         ASSERT(m_jit);
2413         
2414         // This is counter-intuitive but correct. DoubleOperand is intended to
2415         // be used only when you're a node that is happy to accept an untyped
2416         // value, but will special-case for doubles (using DoubleOperand) if the
2417         // value happened to already be represented as a double. The implication
2418         // is that you will not try to force the value to become a double if it
2419         // is not one already.
2420         ASSERT(use.useKind() != DoubleUse);
2421         
2422         if (jit->isFilledDouble(m_index))
2423             fpr();
2424     }
2425
2426     ~DoubleOperand()
2427     {
2428         ASSERT(m_fprOrInvalid != InvalidFPRReg);
2429         m_jit->unlock(m_fprOrInvalid);
2430     }
2431
2432     NodeIndex index() const
2433     {
2434         return m_index;
2435     }
2436
2437     FPRReg fpr()
2438     {
2439         if (m_fprOrInvalid == InvalidFPRReg)
2440             m_fprOrInvalid = m_jit->fillDouble(index());
2441         return m_fprOrInvalid;
2442     }
2443     
2444     void use()
2445     {
2446         m_jit->use(m_index);
2447     }
2448
2449 private:
2450     SpeculativeJIT* m_jit;
2451     NodeIndex m_index;
2452     FPRReg m_fprOrInvalid;
2453 };
2454
2455 class JSValueOperand {
2456 public:
2457     explicit JSValueOperand(SpeculativeJIT* jit, Edge use)
2458         : m_jit(jit)
2459         , m_index(use.index())
2460 #if USE(JSVALUE64)
2461         , m_gprOrInvalid(InvalidGPRReg)
2462 #elif USE(JSVALUE32_64)
2463         , m_isDouble(false)
2464 #endif
2465     {
2466         ASSERT(m_jit);
2467         ASSERT(use.useKind() != DoubleUse);
2468 #if USE(JSVALUE64)
2469         if (jit->isFilled(m_index))
2470             gpr();
2471 #elif USE(JSVALUE32_64)
2472         m_register.pair.tagGPR = InvalidGPRReg;
2473         m_register.pair.payloadGPR = InvalidGPRReg;
2474         if (jit->isFilled(m_index))
2475             fill();
2476 #endif
2477     }
2478
2479     ~JSValueOperand()
2480     {
2481 #if USE(JSVALUE64)
2482         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2483         m_jit->unlock(m_gprOrInvalid);
2484 #elif USE(JSVALUE32_64)
2485         if (m_isDouble) {
2486             ASSERT(m_register.fpr != InvalidFPRReg);
2487             m_jit->unlock(m_register.fpr);
2488         } else {
2489             ASSERT(m_register.pair.tagGPR != InvalidGPRReg && m_register.pair.payloadGPR != InvalidGPRReg);
2490             m_jit->unlock(m_register.pair.tagGPR);
2491             m_jit->unlock(m_register.pair.payloadGPR);
2492         }
2493 #endif
2494     }
2495
2496     NodeIndex index() const
2497     {
2498         return m_index;
2499     }
2500
2501 #if USE(JSVALUE64)
2502     GPRReg gpr()
2503     {
2504         if (m_gprOrInvalid == InvalidGPRReg)
2505             m_gprOrInvalid = m_jit->fillJSValue(index());
2506         return m_gprOrInvalid;
2507     }
2508     JSValueRegs jsValueRegs()
2509     {
2510         return JSValueRegs(gpr());
2511     }
2512 #elif USE(JSVALUE32_64)
2513     bool isDouble() { return m_isDouble; }
2514
2515     void fill()
2516     {
2517         if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg)
2518             m_isDouble = !m_jit->fillJSValue(index(), m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);
2519     }
2520
2521     GPRReg tagGPR()
2522     {
2523         fill();
2524         ASSERT(!m_isDouble);
2525         return m_register.pair.tagGPR;
2526     }
2527
2528     GPRReg payloadGPR()
2529     {
2530         fill();
2531         ASSERT(!m_isDouble);
2532         return m_register.pair.payloadGPR;
2533     }
2534
2535     JSValueRegs jsValueRegs()
2536     {
2537         return JSValueRegs(tagGPR(), payloadGPR());
2538     }
2539
2540     FPRReg fpr()
2541     {
2542         fill();
2543         ASSERT(m_isDouble);
2544         return m_register.fpr;
2545     }
2546 #endif
2547
2548     void use()
2549     {
2550         m_jit->use(m_index);
2551     }
2552
2553 private:
2554     SpeculativeJIT* m_jit;
2555     NodeIndex m_index;
2556 #if USE(JSVALUE64)
2557     GPRReg m_gprOrInvalid;
2558 #elif USE(JSVALUE32_64)
2559     union {
2560         struct {
2561             GPRReg tagGPR;
2562             GPRReg payloadGPR;
2563         } pair;
2564         FPRReg fpr;
2565     } m_register;
2566     bool m_isDouble;
2567 #endif
2568 };
2569
2570 class StorageOperand {
2571 public:
2572     explicit StorageOperand(SpeculativeJIT* jit, Edge use)
2573         : m_jit(jit)
2574         , m_index(use.index())
2575         , m_gprOrInvalid(InvalidGPRReg)
2576     {
2577         ASSERT(m_jit);
2578         ASSERT(use.useKind() != DoubleUse);
2579         if (jit->isFilled(m_index))
2580             gpr();
2581     }
2582     
2583     ~StorageOperand()
2584     {
2585         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2586         m_jit->unlock(m_gprOrInvalid);
2587     }
2588     
2589     NodeIndex index() const
2590     {
2591         return m_index;
2592     }
2593     
2594     GPRReg gpr()
2595     {
2596         if (m_gprOrInvalid == InvalidGPRReg)
2597             m_gprOrInvalid = m_jit->fillStorage(index());
2598         return m_gprOrInvalid;
2599     }
2600     
2601     void use()
2602     {
2603         m_jit->use(m_index);
2604     }
2605     
2606 private:
2607     SpeculativeJIT* m_jit;
2608     NodeIndex m_index;
2609     GPRReg m_gprOrInvalid;
2610 };
2611
2612
2613 // === Temporaries ===
2614 //
2615 // These classes are used to allocate temporary registers.
2616 // A mechanism is provided to attempt to reuse the registers
2617 // currently allocated to child nodes whose value is consumed
2618 // by, and not live after, this operation.
2619
2620 class GPRTemporary {
2621 public:
2622     GPRTemporary();
2623     GPRTemporary(SpeculativeJIT*);
2624     GPRTemporary(SpeculativeJIT*, GPRReg specific);
2625     GPRTemporary(SpeculativeJIT*, SpeculateIntegerOperand&);
2626     GPRTemporary(SpeculativeJIT*, SpeculateIntegerOperand&, SpeculateIntegerOperand&);
2627     GPRTemporary(SpeculativeJIT*, SpeculateStrictInt32Operand&);
2628     GPRTemporary(SpeculativeJIT*, IntegerOperand&);
2629     GPRTemporary(SpeculativeJIT*, IntegerOperand&, IntegerOperand&);
2630     GPRTemporary(SpeculativeJIT*, SpeculateCellOperand&);
2631     GPRTemporary(SpeculativeJIT*, SpeculateBooleanOperand&);
2632 #if USE(JSVALUE64)
2633     GPRTemporary(SpeculativeJIT*, JSValueOperand&);
2634 #elif USE(JSVALUE32_64)
2635     GPRTemporary(SpeculativeJIT*, JSValueOperand&, bool tag = true);
2636 #endif
2637     GPRTemporary(SpeculativeJIT*, StorageOperand&);
2638
2639     void adopt(GPRTemporary&);
2640
2641     ~GPRTemporary()
2642     {
2643         if (m_jit && m_gpr != InvalidGPRReg)
2644             m_jit->unlock(gpr());
2645     }
2646
2647     GPRReg gpr()
2648     {
2649         return m_gpr;
2650     }
2651
2652 private:
2653     SpeculativeJIT* m_jit;
2654     GPRReg m_gpr;
2655 };
2656
2657 class FPRTemporary {
2658 public:
2659     FPRTemporary(SpeculativeJIT*);
2660     FPRTemporary(SpeculativeJIT*, DoubleOperand&);
2661     FPRTemporary(SpeculativeJIT*, DoubleOperand&, DoubleOperand&);
2662     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&);
2663     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
2664 #if USE(JSVALUE32_64)
2665     FPRTemporary(SpeculativeJIT*, JSValueOperand&);
2666 #endif
2667
2668     ~FPRTemporary()
2669     {
2670         m_jit->unlock(fpr());
2671     }
2672
2673     FPRReg fpr() const
2674     {
2675         ASSERT(m_fpr != InvalidFPRReg);
2676         return m_fpr;
2677     }
2678
2679 protected:
2680     FPRTemporary(SpeculativeJIT* jit, FPRReg lockedFPR)
2681         : m_jit(jit)
2682         , m_fpr(lockedFPR)
2683     {
2684     }
2685
2686 private:
2687     SpeculativeJIT* m_jit;
2688     FPRReg m_fpr;
2689 };
2690
2691
2692 // === Results ===
2693 //
2694 // These classes lock the result of a call to a C++ helper function.
2695
2696 class GPRResult : public GPRTemporary {
2697 public:
2698     GPRResult(SpeculativeJIT* jit)
2699         : GPRTemporary(jit, GPRInfo::returnValueGPR)
2700     {
2701     }
2702 };
2703
2704 #if USE(JSVALUE32_64)
2705 class GPRResult2 : public GPRTemporary {
2706 public:
2707     GPRResult2(SpeculativeJIT* jit)
2708         : GPRTemporary(jit, GPRInfo::returnValueGPR2)
2709     {
2710     }
2711 };
2712 #endif
2713
2714 class FPRResult : public FPRTemporary {
2715 public:
2716     FPRResult(SpeculativeJIT* jit)
2717         : FPRTemporary(jit, lockedResult(jit))
2718     {
2719     }
2720
2721 private:
2722     static FPRReg lockedResult(SpeculativeJIT* jit)
2723     {
2724         jit->lock(FPRInfo::returnValueFPR);
2725         return FPRInfo::returnValueFPR;
2726     }
2727 };
2728
2729
2730 // === Speculative Operand types ===
2731 //
2732 // SpeculateIntegerOperand, SpeculateStrictInt32Operand and SpeculateCellOperand.
2733 //
2734 // These are used to lock the operands to a node into machine registers within the
2735 // SpeculativeJIT. The classes operate like those above, however these will
2736 // perform a speculative check for a more restrictive type than we can statically
2737 // determine the operand to have. If the operand does not have the requested type,
2738 // a bail-out to the non-speculative path will be taken.
2739
2740 class SpeculateIntegerOperand {
2741 public:
2742     explicit SpeculateIntegerOperand(SpeculativeJIT* jit, Edge use)
2743         : m_jit(jit)
2744         , m_index(use.index())
2745         , m_gprOrInvalid(InvalidGPRReg)
2746 #ifndef NDEBUG
2747         , m_format(DataFormatNone)
2748 #endif
2749     {
2750         ASSERT(m_jit);
2751         ASSERT(use.useKind() != DoubleUse);
2752         if (jit->isFilled(m_index))
2753             gpr();
2754     }
2755
2756     ~SpeculateIntegerOperand()
2757     {
2758         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2759         m_jit->unlock(m_gprOrInvalid);
2760     }
2761
2762     NodeIndex index() const
2763     {
2764         return m_index;
2765     }
2766
2767     DataFormat format()
2768     {
2769         gpr(); // m_format is set when m_gpr is locked.
2770         ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
2771         return m_format;
2772     }
2773
2774     GPRReg gpr()
2775     {
2776         if (m_gprOrInvalid == InvalidGPRReg)
2777             m_gprOrInvalid = m_jit->fillSpeculateInt(index(), m_format);
2778         return m_gprOrInvalid;
2779     }
2780
2781 private:
2782     SpeculativeJIT* m_jit;
2783     NodeIndex m_index;
2784     GPRReg m_gprOrInvalid;
2785     DataFormat m_format;
2786 };
2787
2788 class SpeculateStrictInt32Operand {
2789 public:
2790     explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge use)
2791         : m_jit(jit)
2792         , m_index(use.index())
2793         , m_gprOrInvalid(InvalidGPRReg)
2794     {
2795         ASSERT(m_jit);
2796         ASSERT(use.useKind() != DoubleUse);
2797         if (jit->isFilled(m_index))
2798             gpr();
2799     }
2800
2801     ~SpeculateStrictInt32Operand()
2802     {
2803         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2804         m_jit->unlock(m_gprOrInvalid);
2805     }
2806
2807     NodeIndex index() const
2808     {
2809         return m_index;
2810     }
2811
2812     GPRReg gpr()
2813     {
2814         if (m_gprOrInvalid == InvalidGPRReg)
2815             m_gprOrInvalid = m_jit->fillSpeculateIntStrict(index());
2816         return m_gprOrInvalid;
2817     }
2818     
2819     void use()
2820     {
2821         m_jit->use(m_index);
2822     }
2823
2824 private:
2825     SpeculativeJIT* m_jit;
2826     NodeIndex m_index;
2827     GPRReg m_gprOrInvalid;
2828 };
2829
2830 class SpeculateDoubleOperand {
2831 public:
2832     explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge use)
2833         : m_jit(jit)
2834         , m_index(use.index())
2835         , m_fprOrInvalid(InvalidFPRReg)
2836     {
2837         ASSERT(m_jit);
2838         ASSERT(use.useKind() == DoubleUse);
2839         if (jit->isFilled(m_index))
2840             fpr();
2841     }
2842
2843     ~SpeculateDoubleOperand()
2844     {
2845         ASSERT(m_fprOrInvalid != InvalidFPRReg);
2846         m_jit->unlock(m_fprOrInvalid);
2847     }
2848
2849     NodeIndex index() const
2850     {
2851         return m_index;
2852     }
2853
2854     FPRReg fpr()
2855     {
2856         if (m_fprOrInvalid == InvalidFPRReg)
2857             m_fprOrInvalid = m_jit->fillSpeculateDouble(index());
2858         return m_fprOrInvalid;
2859     }
2860
2861 private:
2862     SpeculativeJIT* m_jit;
2863     NodeIndex m_index;
2864     FPRReg m_fprOrInvalid;
2865 };
2866
2867 class SpeculateCellOperand {
2868 public:
2869     explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use)
2870         : m_jit(jit)
2871         , m_index(use.index())
2872         , m_gprOrInvalid(InvalidGPRReg)
2873     {
2874         ASSERT(m_jit);
2875         ASSERT(use.useKind() != DoubleUse);
2876         if (jit->isFilled(m_index))
2877             gpr();
2878     }
2879
2880     ~SpeculateCellOperand()
2881     {
2882         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2883         m_jit->unlock(m_gprOrInvalid);
2884     }
2885
2886     NodeIndex index() const
2887     {
2888         return m_index;
2889     }
2890
2891     GPRReg gpr()
2892     {
2893         if (m_gprOrInvalid == InvalidGPRReg)
2894             m_gprOrInvalid = m_jit->fillSpeculateCell(index());
2895         return m_gprOrInvalid;
2896     }
2897     
2898     void use()
2899     {
2900         m_jit->use(m_index);
2901     }
2902
2903 private:
2904     SpeculativeJIT* m_jit;
2905     NodeIndex m_index;
2906     GPRReg m_gprOrInvalid;
2907 };
2908
2909 class SpeculateBooleanOperand {
2910 public:
2911     explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge use)
2912         : m_jit(jit)
2913         , m_index(use.index())
2914         , m_gprOrInvalid(InvalidGPRReg)
2915     {
2916         ASSERT(m_jit);
2917         ASSERT(use.useKind() != DoubleUse);
2918         if (jit->isFilled(m_index))
2919             gpr();
2920     }
2921     
2922     ~SpeculateBooleanOperand()
2923     {
2924         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2925         m_jit->unlock(m_gprOrInvalid);
2926     }
2927     
2928     NodeIndex index() const
2929     {
2930         return m_index;
2931     }
2932     
2933     GPRReg gpr()
2934     {
2935         if (m_gprOrInvalid == InvalidGPRReg)
2936             m_gprOrInvalid = m_jit->fillSpeculateBoolean(index());
2937         return m_gprOrInvalid;
2938     }
2939     
2940     void use()
2941     {
2942         m_jit->use(m_index);
2943     }
2944
2945 private:
2946     SpeculativeJIT* m_jit;
2947     NodeIndex m_index;
2948     GPRReg m_gprOrInvalid;
2949 };
2950
2951 } } // namespace JSC::DFG
2952
2953 #endif
2954 #endif
2955