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