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