op_mod fails on many interesting corner cases
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "JSByteArray.h"
32 #include "LinkBuffer.h"
33
34 namespace JSC { namespace DFG {
35
36 // On Windows we need to wrap fmod; on other platforms we can call it directly.
37 // On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
38 #if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
39 static double DFG_OPERATION fmodAsDFGOperation(double x, double y)
40 {
41     return fmod(x, y);
42 }
43 #else
44 #define fmodAsDFGOperation fmod
45 #endif
46
47 void SpeculativeJIT::clearGenerationInfo()
48 {
49     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
50         m_generationInfo[i] = GenerationInfo();
51     m_gprs = RegisterBank<GPRInfo>();
52     m_fprs = RegisterBank<FPRInfo>();
53 }
54
55 GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
56 {
57     Node& node = m_jit.graph()[nodeIndex];
58     VirtualRegister virtualRegister = node.virtualRegister();
59     GenerationInfo& info = m_generationInfo[virtualRegister];
60     
61     switch (info.registerFormat()) {
62     case DataFormatNone: {
63         GPRReg gpr = allocate();
64         ASSERT(info.spillFormat() == DataFormatStorage);
65         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
66         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
67         info.fillStorage(gpr);
68         return gpr;
69     }
70         
71     case DataFormatStorage: {
72         GPRReg gpr = info.gpr();
73         m_gprs.lock(gpr);
74         return gpr;
75     }
76         
77     default:
78         ASSERT_NOT_REACHED();
79     }
80     
81     return InvalidGPRReg;
82 }
83
84 void SpeculativeJIT::useChildren(Node& node)
85 {
86     if (node.flags() & NodeHasVarArgs) {
87         for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
88             use(m_jit.graph().m_varArgChildren[childIdx]);
89     } else {
90         Edge child1 = node.child1();
91         if (!child1) {
92             ASSERT(!node.child2() && !node.child3());
93             return;
94         }
95         use(child1);
96         
97         Edge child2 = node.child2();
98         if (!child2) {
99             ASSERT(!node.child3());
100             return;
101         }
102         use(child2);
103         
104         Edge child3 = node.child3();
105         if (!child3)
106             return;
107         use(child3);
108     }
109 }
110
111 bool SpeculativeJIT::isStrictInt32(NodeIndex nodeIndex)
112 {
113     if (isInt32Constant(nodeIndex))
114         return true;
115     
116     Node& node = m_jit.graph()[nodeIndex];
117     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
118     
119     return info.registerFormat() == DataFormatInteger;
120 }
121
122 bool SpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
123 {
124     if (isInt32Constant(nodeIndex))
125         return true;
126
127     Node& node = m_jit.graph()[nodeIndex];
128     
129     if (node.hasInt32Result())
130         return true;
131     
132     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
133
134     return info.isJSInteger();
135 }
136
137 bool SpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
138 {
139     if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))
140         return true;
141
142     Node& node = m_jit.graph()[nodeIndex];
143     
144     if (node.hasNumberResult())
145         return true;
146     
147     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
148
149     return info.isJSInteger() || info.isJSDouble();
150 }
151
152 bool SpeculativeJIT::isKnownCell(NodeIndex nodeIndex)
153 {
154     return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();
155 }
156
157 bool SpeculativeJIT::isKnownNotCell(NodeIndex nodeIndex)
158 {
159     Node& node = m_jit.graph()[nodeIndex];
160     VirtualRegister virtualRegister = node.virtualRegister();
161     GenerationInfo& info = m_generationInfo[virtualRegister];
162     if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell())
163         return true;
164     return !(info.isJSCell() || info.isUnknownJS());
165 }
166
167 bool SpeculativeJIT::isKnownNotInteger(NodeIndex nodeIndex)
168 {
169     Node& node = m_jit.graph()[nodeIndex];
170     VirtualRegister virtualRegister = node.virtualRegister();
171     GenerationInfo& info = m_generationInfo[virtualRegister];
172     
173     return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()
174         || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());
175 }
176
177 bool SpeculativeJIT::isKnownNotNumber(NodeIndex nodeIndex)
178 {
179     Node& node = m_jit.graph()[nodeIndex];
180     VirtualRegister virtualRegister = node.virtualRegister();
181     GenerationInfo& info = m_generationInfo[virtualRegister];
182     
183     return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())
184         || (node.hasConstant() && !isNumberConstant(nodeIndex));
185 }
186
187 bool SpeculativeJIT::isKnownBoolean(NodeIndex nodeIndex)
188 {
189     Node& node = m_jit.graph()[nodeIndex];
190     if (node.hasBooleanResult())
191         return true;
192     
193     if (isBooleanConstant(nodeIndex))
194         return true;
195     
196     VirtualRegister virtualRegister = node.virtualRegister();
197     GenerationInfo& info = m_generationInfo[virtualRegister];
198     
199     return info.isJSBoolean();
200 }
201
202 bool SpeculativeJIT::isKnownNotBoolean(NodeIndex nodeIndex)
203 {
204     Node& node = m_jit.graph()[nodeIndex];
205     VirtualRegister virtualRegister = node.virtualRegister();
206     GenerationInfo& info = m_generationInfo[virtualRegister];
207     if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isBoolean())
208         return true;
209     return !(info.isJSBoolean() || info.isUnknownJS());
210 }
211
212 void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
213 {
214     UNUSED_PARAM(jit);
215     UNUSED_PARAM(owner);
216     UNUSED_PARAM(scratch1);
217     UNUSED_PARAM(scratch2);
218     UNUSED_PARAM(useKind);
219     ASSERT(owner != scratch1);
220     ASSERT(owner != scratch2);
221     ASSERT(scratch1 != scratch2);
222
223 #if ENABLE(WRITE_BARRIER_PROFILING)
224     JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
225 #endif
226     markCellCard(jit, owner, scratch1, scratch2);
227 }
228
229 void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2)
230 {
231     UNUSED_PARAM(jit);
232     UNUSED_PARAM(owner);
233     UNUSED_PARAM(scratch1);
234     UNUSED_PARAM(scratch2);
235     
236 #if ENABLE(GGC)
237     jit.move(owner, scratch1);
238     jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1);
239     jit.move(owner, scratch2);
240     // consume additional 8 bits as we're using an approximate filter
241     jit.rshift32(TrustedImm32(MarkedBlock::atomShift + 8), scratch2);
242     jit.andPtr(TrustedImm32(MarkedBlock::atomMask >> 8), scratch2);
243     MacroAssembler::Jump filter = jit.branchTest8(MacroAssembler::Zero, MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfMarks()));
244     jit.move(owner, scratch2);
245     jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2);
246     jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2);
247     jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards()));
248     filter.link(&jit);
249 #endif
250 }
251
252 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
253 {
254     UNUSED_PARAM(ownerGPR);
255     UNUSED_PARAM(valueGPR);
256     UNUSED_PARAM(scratch1);
257     UNUSED_PARAM(scratch2);
258     UNUSED_PARAM(useKind);
259
260     if (isKnownNotCell(valueUse.index()))
261         return;
262
263 #if ENABLE(WRITE_BARRIER_PROFILING)
264     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
265 #endif
266
267 #if ENABLE(GGC)
268     GPRTemporary temp1;
269     GPRTemporary temp2;
270     if (scratch1 == InvalidGPRReg) {
271         GPRTemporary scratchGPR(this);
272         temp1.adopt(scratchGPR);
273         scratch1 = temp1.gpr();
274     }
275     if (scratch2 == InvalidGPRReg) {
276         GPRTemporary scratchGPR(this);
277         temp2.adopt(scratchGPR);
278         scratch2 = temp2.gpr();
279     }
280     
281     JITCompiler::Jump rhsNotCell;
282     bool hadCellCheck = false;
283     if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
284         hadCellCheck = true;
285         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
286     }
287
288     markCellCard(m_jit, ownerGPR, scratch1, scratch2);
289
290     if (hadCellCheck)
291         rhsNotCell.link(&m_jit);
292 #endif
293 }
294
295 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
296 {
297     UNUSED_PARAM(ownerGPR);
298     UNUSED_PARAM(value);
299     UNUSED_PARAM(scratch1);
300     UNUSED_PARAM(scratch2);
301     UNUSED_PARAM(useKind);
302     
303     if (Heap::isMarked(value))
304         return;
305
306 #if ENABLE(WRITE_BARRIER_PROFILING)
307     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
308 #endif
309
310 #if ENABLE(GGC)
311     GPRTemporary temp1;
312     GPRTemporary temp2;
313     if (scratch1 == InvalidGPRReg) {
314         GPRTemporary scratchGPR(this);
315         temp1.adopt(scratchGPR);
316         scratch1 = temp1.gpr();
317     }
318     if (scratch2 == InvalidGPRReg) {
319         GPRTemporary scratchGPR(this);
320         temp2.adopt(scratchGPR);
321         scratch2 = temp2.gpr();
322     }
323
324     markCellCard(m_jit, ownerGPR, scratch1, scratch2);
325 #endif
326 }
327
328 void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch)
329 {
330     UNUSED_PARAM(owner);
331     UNUSED_PARAM(valueGPR);
332     UNUSED_PARAM(scratch);
333     UNUSED_PARAM(useKind);
334
335     if (isKnownNotCell(valueUse.index()))
336         return;
337
338 #if ENABLE(WRITE_BARRIER_PROFILING)
339     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
340 #endif
341
342 #if ENABLE(GGC)
343     JITCompiler::Jump rhsNotCell;
344     bool hadCellCheck = false;
345     if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
346         hadCellCheck = true;
347         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
348     }
349     
350     GPRTemporary temp;
351     if (scratch == InvalidGPRReg) {
352         GPRTemporary scratchGPR(this);
353         temp.adopt(scratchGPR);
354         scratch = temp.gpr();
355     }
356
357     uint8_t* cardAddress = Heap::addressOfCardFor(owner);
358     m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch);
359     m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch));
360
361     if (hadCellCheck)
362         rhsNotCell.link(&m_jit);
363 #endif
364 }
365
366 bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
367 {
368     unsigned branchIndexInBlock = detectPeepHoleBranch();
369     if (branchIndexInBlock != UINT_MAX) {
370         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
371
372         ASSERT(node.adjustedRefCount() == 1);
373         
374         nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);
375     
376         m_indexInBlock = branchIndexInBlock;
377         m_compileIndex = branchNodeIndex;
378         
379         return true;
380     }
381     
382     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
383     
384     return false;
385 }
386
387 bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert)
388 {
389     unsigned branchIndexInBlock = detectPeepHoleBranch();
390     if (branchIndexInBlock != UINT_MAX) {
391         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
392
393         ASSERT(node.adjustedRefCount() == 1);
394         
395         nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
396     
397         m_indexInBlock = branchIndexInBlock;
398         m_compileIndex = branchNodeIndex;
399         
400         return true;
401     }
402     
403     nonSpeculativeNonPeepholeStrictEq(node, invert);
404     
405     return false;
406 }
407
408 #ifndef NDEBUG
409 static const char* dataFormatString(DataFormat format)
410 {
411     // These values correspond to the DataFormat enum.
412     const char* strings[] = {
413         "[  ]",
414         "[ i]",
415         "[ d]",
416         "[ c]",
417         "Err!",
418         "Err!",
419         "Err!",
420         "Err!",
421         "[J ]",
422         "[Ji]",
423         "[Jd]",
424         "[Jc]",
425         "Err!",
426         "Err!",
427         "Err!",
428         "Err!",
429     };
430     return strings[format];
431 }
432
433 void SpeculativeJIT::dump(const char* label)
434 {
435     if (label)
436         dataLog("<%s>\n", label);
437
438     dataLog("  gprs:\n");
439     m_gprs.dump();
440     dataLog("  fprs:\n");
441     m_fprs.dump();
442     dataLog("  VirtualRegisters:\n");
443     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
444         GenerationInfo& info = m_generationInfo[i];
445         if (info.alive())
446             dataLog("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
447         else
448             dataLog("    % 3d:[__][__]", i);
449         if (info.registerFormat() == DataFormatDouble)
450             dataLog(":fpr%d\n", info.fpr());
451         else if (info.registerFormat() != DataFormatNone
452 #if USE(JSVALUE32_64)
453             && !(info.registerFormat() & DataFormatJS)
454 #endif
455             ) {
456             ASSERT(info.gpr() != InvalidGPRReg);
457             dataLog(":%s\n", GPRInfo::debugName(info.gpr()));
458         } else
459             dataLog("\n");
460     }
461     if (label)
462         dataLog("</%s>\n", label);
463 }
464 #endif
465
466
467 #if DFG_ENABLE(CONSISTENCY_CHECK)
468 void SpeculativeJIT::checkConsistency()
469 {
470     bool failed = false;
471
472     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
473         if (iter.isLocked()) {
474             dataLog("DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
475             failed = true;
476         }
477     }
478     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
479         if (iter.isLocked()) {
480             dataLog("DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
481             failed = true;
482         }
483     }
484
485     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
486         VirtualRegister virtualRegister = (VirtualRegister)i;
487         GenerationInfo& info = m_generationInfo[virtualRegister];
488         if (!info.alive())
489             continue;
490         switch (info.registerFormat()) {
491         case DataFormatNone:
492             break;
493         case DataFormatJS:
494         case DataFormatJSInteger:
495         case DataFormatJSDouble:
496         case DataFormatJSCell:
497         case DataFormatJSBoolean:
498 #if USE(JSVALUE32_64)
499             break;
500 #endif
501         case DataFormatInteger:
502         case DataFormatCell:
503         case DataFormatBoolean:
504         case DataFormatStorage: {
505             GPRReg gpr = info.gpr();
506             ASSERT(gpr != InvalidGPRReg);
507             if (m_gprs.name(gpr) != virtualRegister) {
508                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
509                 failed = true;
510             }
511             break;
512         }
513         case DataFormatDouble: {
514             FPRReg fpr = info.fpr();
515             ASSERT(fpr != InvalidFPRReg);
516             if (m_fprs.name(fpr) != virtualRegister) {
517                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
518                 failed = true;
519             }
520             break;
521         }
522         }
523     }
524
525     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
526         VirtualRegister virtualRegister = iter.name();
527         if (virtualRegister == InvalidVirtualRegister)
528             continue;
529
530         GenerationInfo& info = m_generationInfo[virtualRegister];
531 #if USE(JSVALUE64)
532         if (iter.regID() != info.gpr()) {
533             dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
534             failed = true;
535         }
536 #else
537         if (!(info.registerFormat() & DataFormatJS)) {
538             if (iter.regID() != info.gpr()) {
539                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
540                 failed = true;
541             }
542         } else {
543             if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) {
544                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
545                 failed = true;
546             }
547         }
548 #endif
549     }
550
551     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
552         VirtualRegister virtualRegister = iter.name();
553         if (virtualRegister == InvalidVirtualRegister)
554             continue;
555
556         GenerationInfo& info = m_generationInfo[virtualRegister];
557         if (iter.regID() != info.fpr()) {
558             dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
559             failed = true;
560         }
561     }
562
563     if (failed) {
564         dump();
565         CRASH();
566     }
567 }
568 #endif
569
570 GPRTemporary::GPRTemporary()
571     : m_jit(0)
572     , m_gpr(InvalidGPRReg)
573 {
574 }
575
576 GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
577     : m_jit(jit)
578     , m_gpr(InvalidGPRReg)
579 {
580     m_gpr = m_jit->allocate();
581 }
582
583 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
584     : m_jit(jit)
585     , m_gpr(InvalidGPRReg)
586 {
587     m_gpr = m_jit->allocate(specific);
588 }
589
590 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateIntegerOperand& op1)
591     : m_jit(jit)
592     , m_gpr(InvalidGPRReg)
593 {
594     if (m_jit->canReuse(op1.index()))
595         m_gpr = m_jit->reuse(op1.gpr());
596     else
597         m_gpr = m_jit->allocate();
598 }
599
600 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
601     : m_jit(jit)
602     , m_gpr(InvalidGPRReg)
603 {
604     if (m_jit->canReuse(op1.index()))
605         m_gpr = m_jit->reuse(op1.gpr());
606     else if (m_jit->canReuse(op2.index()))
607         m_gpr = m_jit->reuse(op2.gpr());
608     else
609         m_gpr = m_jit->allocate();
610 }
611
612 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateStrictInt32Operand& op1)
613     : m_jit(jit)
614     , m_gpr(InvalidGPRReg)
615 {
616     if (m_jit->canReuse(op1.index()))
617         m_gpr = m_jit->reuse(op1.gpr());
618     else
619         m_gpr = m_jit->allocate();
620 }
621
622 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, IntegerOperand& op1)
623     : m_jit(jit)
624     , m_gpr(InvalidGPRReg)
625 {
626     if (m_jit->canReuse(op1.index()))
627         m_gpr = m_jit->reuse(op1.gpr());
628     else
629         m_gpr = m_jit->allocate();
630 }
631
632 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, IntegerOperand& op1, IntegerOperand& op2)
633     : m_jit(jit)
634     , m_gpr(InvalidGPRReg)
635 {
636     if (m_jit->canReuse(op1.index()))
637         m_gpr = m_jit->reuse(op1.gpr());
638     else if (m_jit->canReuse(op2.index()))
639         m_gpr = m_jit->reuse(op2.gpr());
640     else
641         m_gpr = m_jit->allocate();
642 }
643
644 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateCellOperand& op1)
645     : m_jit(jit)
646     , m_gpr(InvalidGPRReg)
647 {
648     if (m_jit->canReuse(op1.index()))
649         m_gpr = m_jit->reuse(op1.gpr());
650     else
651         m_gpr = m_jit->allocate();
652 }
653
654 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateBooleanOperand& op1)
655     : m_jit(jit)
656     , m_gpr(InvalidGPRReg)
657 {
658     if (m_jit->canReuse(op1.index()))
659         m_gpr = m_jit->reuse(op1.gpr());
660     else
661         m_gpr = m_jit->allocate();
662 }
663
664 #if USE(JSVALUE64)
665 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
666     : m_jit(jit)
667     , m_gpr(InvalidGPRReg)
668 {
669     if (m_jit->canReuse(op1.index()))
670         m_gpr = m_jit->reuse(op1.gpr());
671     else
672         m_gpr = m_jit->allocate();
673 }
674 #else
675 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1, bool tag)
676     : m_jit(jit)
677     , m_gpr(InvalidGPRReg)
678 {
679     if (!op1.isDouble() && m_jit->canReuse(op1.index()))
680         m_gpr = m_jit->reuse(tag ? op1.tagGPR() : op1.payloadGPR());
681     else
682         m_gpr = m_jit->allocate();
683 }
684 #endif
685
686 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, StorageOperand& op1)
687     : m_jit(jit)
688     , m_gpr(InvalidGPRReg)
689 {
690     if (m_jit->canReuse(op1.index()))
691         m_gpr = m_jit->reuse(op1.gpr());
692     else
693         m_gpr = m_jit->allocate();
694 }
695
696 void GPRTemporary::adopt(GPRTemporary& other)
697 {
698     ASSERT(!m_jit);
699     ASSERT(m_gpr == InvalidGPRReg);
700     ASSERT(other.m_jit);
701     ASSERT(other.m_gpr != InvalidGPRReg);
702     m_jit = other.m_jit;
703     m_gpr = other.m_gpr;
704     other.m_jit = 0;
705     other.m_gpr = InvalidGPRReg;
706 }
707
708 FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
709     : m_jit(jit)
710     , m_fpr(InvalidFPRReg)
711 {
712     m_fpr = m_jit->fprAllocate();
713 }
714
715 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1)
716     : m_jit(jit)
717     , m_fpr(InvalidFPRReg)
718 {
719     if (m_jit->canReuse(op1.index()))
720         m_fpr = m_jit->reuse(op1.fpr());
721     else
722         m_fpr = m_jit->fprAllocate();
723 }
724
725 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1, DoubleOperand& op2)
726     : m_jit(jit)
727     , m_fpr(InvalidFPRReg)
728 {
729     if (m_jit->canReuse(op1.index()))
730         m_fpr = m_jit->reuse(op1.fpr());
731     else if (m_jit->canReuse(op2.index()))
732         m_fpr = m_jit->reuse(op2.fpr());
733     else
734         m_fpr = m_jit->fprAllocate();
735 }
736
737 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1)
738     : m_jit(jit)
739     , m_fpr(InvalidFPRReg)
740 {
741     if (m_jit->canReuse(op1.index()))
742         m_fpr = m_jit->reuse(op1.fpr());
743     else
744         m_fpr = m_jit->fprAllocate();
745 }
746
747 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
748     : m_jit(jit)
749     , m_fpr(InvalidFPRReg)
750 {
751     if (m_jit->canReuse(op1.index()))
752         m_fpr = m_jit->reuse(op1.fpr());
753     else if (m_jit->canReuse(op2.index()))
754         m_fpr = m_jit->reuse(op2.fpr());
755     else
756         m_fpr = m_jit->fprAllocate();
757 }
758
759 #if USE(JSVALUE32_64)
760 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
761     : m_jit(jit)
762     , m_fpr(InvalidFPRReg)
763 {
764     if (op1.isDouble() && m_jit->canReuse(op1.index()))
765         m_fpr = m_jit->reuse(op1.fpr());
766     else
767         m_fpr = m_jit->fprAllocate();
768 }
769 #endif
770
771 void ValueSource::dump(FILE* out) const
772 {
773     switch (kind()) {
774     case SourceNotSet:
775         fprintf(out, "NotSet");
776         break;
777     case ValueInRegisterFile:
778         fprintf(out, "InRegFile");
779         break;
780     case Int32InRegisterFile:
781         fprintf(out, "Int32");
782         break;
783     case CellInRegisterFile:
784         fprintf(out, "Cell");
785         break;
786     case BooleanInRegisterFile:
787         fprintf(out, "Bool");
788         break;
789     case DoubleInRegisterFile:
790         fprintf(out, "Double");
791         break;
792     case HaveNode:
793         fprintf(out, "Node(%d)", m_nodeIndex);
794         break;
795     }
796 }
797
798 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
799 {
800     Node& branchNode = at(branchNodeIndex);
801     BlockIndex taken = branchNode.takenBlockIndex();
802     BlockIndex notTaken = branchNode.notTakenBlockIndex();
803     
804     SpeculateDoubleOperand op1(this, node.child1());
805     SpeculateDoubleOperand op2(this, node.child2());
806     
807     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
808     jump(notTaken);
809 }
810
811 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
812 {
813     Node& branchNode = at(branchNodeIndex);
814     BlockIndex taken = branchNode.takenBlockIndex();
815     BlockIndex notTaken = branchNode.notTakenBlockIndex();
816
817     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
818     
819     if (taken == (m_block + 1)) {
820         condition = MacroAssembler::NotEqual;
821         BlockIndex tmp = taken;
822         taken = notTaken;
823         notTaken = tmp;
824     }
825
826     SpeculateCellOperand op1(this, node.child1());
827     SpeculateCellOperand op2(this, node.child2());
828     
829     GPRReg op1GPR = op1.gpr();
830     GPRReg op2GPR = op2.gpr();
831     
832     if (!predictionCheck(m_state.forNode(node.child1()).m_type))
833         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
834     if (!predictionCheck(m_state.forNode(node.child2()).m_type))
835         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
836     
837     branchPtr(condition, op1GPR, op2GPR, taken);
838     jump(notTaken);
839 }
840
841 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
842 {
843     Node& branchNode = at(branchNodeIndex);
844     BlockIndex taken = branchNode.takenBlockIndex();
845     BlockIndex notTaken = branchNode.notTakenBlockIndex();
846
847     // The branch instruction will branch to the taken block.
848     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
849     if (taken == (m_block + 1)) {
850         condition = JITCompiler::invert(condition);
851         BlockIndex tmp = taken;
852         taken = notTaken;
853         notTaken = tmp;
854     }
855
856     if (isInt32Constant(node.child1().index())) {
857         int32_t imm = valueOfInt32Constant(node.child1().index());
858         SpeculateIntegerOperand op2(this, node.child2());
859         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
860     } else if (isInt32Constant(node.child2().index())) {
861         SpeculateIntegerOperand op1(this, node.child1());
862         int32_t imm = valueOfInt32Constant(node.child2().index());
863         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
864     } else {
865         SpeculateIntegerOperand op1(this, node.child1());
866         SpeculateIntegerOperand op2(this, node.child2());
867         branch32(condition, op1.gpr(), op2.gpr(), taken);
868     }
869
870     jump(notTaken);
871 }
872
873 // Returns true if the compare is fused with a subsequent branch.
874 bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
875 {
876     // Fused compare & branch.
877     unsigned branchIndexInBlock = detectPeepHoleBranch();
878     if (branchIndexInBlock != UINT_MAX) {
879         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
880
881         // detectPeepHoleBranch currently only permits the branch to be the very next node,
882         // so can be no intervening nodes to also reference the compare. 
883         ASSERT(node.adjustedRefCount() == 1);
884
885         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
886             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
887             use(node.child1());
888             use(node.child2());
889         } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
890             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
891             use(node.child1());
892             use(node.child2());
893         } else if (node.op() == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
894             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
895             use(node.child1());
896             use(node.child2());
897         } else if (node.op() == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
898             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
899             use(node.child1());
900             use(node.child2());
901         } else
902             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
903
904         m_indexInBlock = branchIndexInBlock;
905         m_compileIndex = branchNodeIndex;
906         return true;
907     }
908     return false;
909 }
910
911 void SpeculativeJIT::compileMovHint(Node& node)
912 {
913     ASSERT(node.op() == SetLocal);
914     
915     setNodeIndexForOperand(node.child1().index(), node.local());
916     m_lastSetOperand = node.local();
917 }
918
919 void SpeculativeJIT::compile(BasicBlock& block)
920 {
921     ASSERT(m_compileOkay);
922     
923     if (!block.isReachable)
924         return;
925
926     m_blockHeads[m_block] = m_jit.label();
927 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
928     m_jit.breakpoint();
929 #endif
930
931     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
932     for (size_t i = 0; i < m_arguments.size(); ++i) {
933         NodeIndex nodeIndex = block.variablesAtHead.argument(i);
934         if (nodeIndex == NoNode || m_jit.graph().argumentIsCaptured(i))
935             m_arguments[i] = ValueSource(ValueInRegisterFile);
936         else
937             m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
938     }
939     
940     m_state.reset();
941     m_state.beginBasicBlock(&block);
942     
943     ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
944     for (size_t i = 0; i < m_variables.size(); ++i) {
945         NodeIndex nodeIndex = block.variablesAtHead.local(i);
946         if (nodeIndex == NoNode || m_jit.graph().localIsCaptured(i))
947             m_variables[i] = ValueSource(ValueInRegisterFile);
948         else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
949             m_variables[i] = ValueSource(DoubleInRegisterFile);
950         else
951             m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
952     }
953     
954     m_lastSetOperand = std::numeric_limits<int>::max();
955     m_codeOriginForOSR = CodeOrigin();
956     
957     if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
958         JITCompiler::Jump verificationSucceeded =
959             m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, TrustedImm32(m_block));
960         m_jit.breakpoint();
961         verificationSucceeded.link(&m_jit);
962     }
963
964     for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
965         m_compileIndex = block[m_indexInBlock];
966         Node& node = at(m_compileIndex);
967         m_codeOriginForOSR = node.codeOrigin;
968         if (!node.shouldGenerate()) {
969 #if DFG_ENABLE(DEBUG_VERBOSE)
970             dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
971 #endif
972             switch (node.op()) {
973             case SetLocal:
974                 compileMovHint(node);
975                 break;
976
977             case InlineStart: {
978                 InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
979                 int argumentCountIncludingThis = inlineCallFrame->arguments.size();
980                 for (int i = 0; i < argumentCountIncludingThis; ++i) {
981                     ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
982                     // The recovery cannot point to registers, since the call frame reification isn't
983                     // as smart as OSR, so it can't handle that. The exception is the this argument,
984                     // which we don't really need to be able to recover.
985                     ASSERT(!i || !recovery.isInRegisters());
986                     inlineCallFrame->arguments[i] = recovery;
987                 }
988                 break;
989             }
990                 
991             default:
992                 break;
993             }
994         } else {
995             
996 #if DFG_ENABLE(DEBUG_VERBOSE)
997             dataLog("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
998 #endif
999 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
1000             m_jit.breakpoint();
1001 #endif
1002 #if DFG_ENABLE(XOR_DEBUG_AID)
1003             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1004             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1005 #endif
1006             checkConsistency();
1007             compile(node);
1008             if (!m_compileOkay) {
1009                 m_compileOkay = true;
1010                 clearGenerationInfo();
1011                 return;
1012             }
1013             
1014 #if DFG_ENABLE(DEBUG_VERBOSE)
1015             if (node.hasResult()) {
1016                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
1017                 dataLog("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
1018                 if (info.registerFormat() != DataFormatNone) {
1019                     if (info.registerFormat() == DataFormatDouble)
1020                         dataLog(", %s", FPRInfo::debugName(info.fpr()));
1021 #if USE(JSVALUE32_64)
1022                     else if (info.registerFormat() & DataFormatJS)
1023                         dataLog(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
1024 #endif
1025                     else
1026                         dataLog(", %s", GPRInfo::debugName(info.gpr()));
1027                 }
1028                 dataLog("    ");
1029             } else
1030                 dataLog("    ");
1031 #endif
1032         }
1033         
1034 #if DFG_ENABLE(VERBOSE_VALUE_RECOVERIES)
1035         for (size_t i = 0; i < m_arguments.size(); ++i)
1036             computeValueRecoveryFor(argumentToOperand(i)).dump(stderr);
1037         
1038         dataLog(" : ");
1039         
1040         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
1041             computeValueRecoveryFor(operand).dump(stderr);
1042 #endif
1043
1044 #if DFG_ENABLE(DEBUG_VERBOSE)
1045         dataLog("\n");
1046 #endif
1047         
1048         // Make sure that the abstract state is rematerialized for the next node.
1049         m_state.execute(m_indexInBlock);
1050         
1051         if (node.shouldGenerate())
1052             checkConsistency();
1053     }
1054     
1055     // Perform the most basic verification that children have been used correctly.
1056 #if !ASSERT_DISABLED
1057     for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1058         GenerationInfo& info = m_generationInfo[index];
1059         ASSERT(!info.alive());
1060     }
1061 #endif
1062 }
1063
1064 // If we are making type predictions about our arguments then
1065 // we need to check that they are correct on function entry.
1066 void SpeculativeJIT::checkArgumentTypes()
1067 {
1068     ASSERT(!m_compileIndex);
1069     m_codeOriginForOSR = CodeOrigin(0);
1070
1071     for (size_t i = 0; i < m_arguments.size(); ++i)
1072         m_arguments[i] = ValueSource(ValueInRegisterFile);
1073     for (size_t i = 0; i < m_variables.size(); ++i)
1074         m_variables[i] = ValueSource(ValueInRegisterFile);
1075     
1076     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1077         NodeIndex nodeIndex = m_jit.graph().m_arguments[i];
1078         Node& node = at(nodeIndex);
1079         ASSERT(node.op() == SetArgument);
1080         if (!node.shouldGenerate()) {
1081             // The argument is dead. We don't do any checks for such arguments.
1082             continue;
1083         }
1084         
1085         VariableAccessData* variableAccessData = node.variableAccessData();
1086         VirtualRegister virtualRegister = variableAccessData->local();
1087         PredictedType predictedType = variableAccessData->prediction();
1088
1089         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1090         
1091 #if USE(JSVALUE64)
1092         if (isInt32Prediction(predictedType))
1093             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1094         else if (isArrayPrediction(predictedType)) {
1095             GPRTemporary temp(this);
1096             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1097             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1098             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
1099         } else if (isByteArrayPrediction(predictedType)) {
1100             GPRTemporary temp(this);
1101             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1102             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1103             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1104         } else if (isBooleanPrediction(predictedType)) {
1105             GPRTemporary temp(this);
1106             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1107             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1108             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1109         } else if (isInt8ArrayPrediction(predictedType)) {
1110             GPRTemporary temp(this);
1111             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1112             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1113             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
1114         } else if (isInt16ArrayPrediction(predictedType)) {
1115             GPRTemporary temp(this);
1116             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1117             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1118             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
1119         } else if (isInt32ArrayPrediction(predictedType)) {
1120             GPRTemporary temp(this);
1121             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1122             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1123             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
1124         } else if (isUint8ArrayPrediction(predictedType)) {
1125             GPRTemporary temp(this);
1126             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1127             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1128             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
1129         } else if (isUint8ClampedArrayPrediction(predictedType)) {
1130             GPRTemporary temp(this);
1131             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1132             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1133             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
1134         } else if (isUint16ArrayPrediction(predictedType)) {
1135             GPRTemporary temp(this);
1136             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1137             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1138             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
1139         } else if (isUint32ArrayPrediction(predictedType)) {
1140             GPRTemporary temp(this);
1141             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1142             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1143             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
1144         } else if (isFloat32ArrayPrediction(predictedType)) {
1145             GPRTemporary temp(this);
1146             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1147             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1148             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
1149         } else if (isFloat64ArrayPrediction(predictedType)) {
1150             GPRTemporary temp(this);
1151             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1152             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1153             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
1154         }
1155 #else
1156         if (isInt32Prediction(predictedType))
1157             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1158         else if (isArrayPrediction(predictedType)) {
1159             GPRTemporary temp(this);
1160             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1161             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1162             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1163             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
1164         } else if (isByteArrayPrediction(predictedType)) {
1165             GPRTemporary temp(this);
1166             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1167             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1168             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1169             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1170         } else if (isBooleanPrediction(predictedType))
1171             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1172         else if (isInt8ArrayPrediction(predictedType)) {
1173             GPRTemporary temp(this);
1174             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1175             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1176             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1177             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
1178         } else if (isInt16ArrayPrediction(predictedType)) {
1179             GPRTemporary temp(this);
1180             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1181             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1182             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1183             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
1184         } else if (isInt32ArrayPrediction(predictedType)) {
1185             GPRTemporary temp(this);
1186             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1187             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1188             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1189             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
1190         } else if (isUint8ArrayPrediction(predictedType)) {
1191             GPRTemporary temp(this);
1192             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1193             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1194             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1195             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
1196         } else if (isUint8ClampedArrayPrediction(predictedType)) {
1197             GPRTemporary temp(this);
1198             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1199             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1200             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1201             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
1202         } else if (isUint16ArrayPrediction(predictedType)) {
1203             GPRTemporary temp(this);
1204             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1205             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1206             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1207             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
1208         }  else if (isUint32ArrayPrediction(predictedType)) {
1209             GPRTemporary temp(this);
1210             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1211             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1212             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1213             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
1214         }  else if (isFloat32ArrayPrediction(predictedType)) {
1215             GPRTemporary temp(this);
1216             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1217             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1218             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1219             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
1220         }   else if (isFloat64ArrayPrediction(predictedType)) {
1221             GPRTemporary temp(this);
1222             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1223             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1224             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1225             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
1226         } 
1227 #endif
1228     }
1229 }
1230
1231 bool SpeculativeJIT::compile()
1232 {
1233     checkArgumentTypes();
1234
1235     if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
1236         m_jit.move(TrustedImm32(0), GPRInfo::regT0);
1237
1238     ASSERT(!m_compileIndex);
1239     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
1240         compile(*m_jit.graph().m_blocks[m_block]);
1241     linkBranches();
1242     return true;
1243 }
1244
1245 void SpeculativeJIT::createOSREntries()
1246 {
1247     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1248         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
1249         if (!block.isOSRTarget)
1250             continue;
1251
1252         // Currently we only need to create OSR entry trampolines when using edge code
1253         // verification. But in the future, we'll need this for other things as well (like
1254         // when we have global reg alloc).
1255         // If we don't need OSR entry trampolin
1256         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1257             m_osrEntryHeads.append(m_blockHeads[blockIndex]);
1258             continue;
1259         }
1260         
1261         m_osrEntryHeads.append(m_jit.label());
1262         m_jit.move(TrustedImm32(blockIndex), GPRInfo::regT0);
1263         m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
1264     }
1265 }
1266
1267 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1268 {
1269     unsigned osrEntryIndex = 0;
1270     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1271         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
1272         if (block.isOSRTarget)
1273             m_jit.noticeOSREntry(block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1274     }
1275     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1276 }
1277
1278 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
1279 {
1280     switch (valueSource.kind()) {
1281     case ValueInRegisterFile:
1282         return ValueRecovery::alreadyInRegisterFile();
1283         
1284     case Int32InRegisterFile:
1285         return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
1286
1287     case CellInRegisterFile:
1288         return ValueRecovery::alreadyInRegisterFileAsUnboxedCell();
1289
1290     case BooleanInRegisterFile:
1291         return ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean();
1292         
1293     case DoubleInRegisterFile:
1294         return ValueRecovery::alreadyInRegisterFileAsUnboxedDouble();
1295
1296     case HaveNode: {
1297         if (isConstant(valueSource.nodeIndex()))
1298             return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
1299     
1300         Node* nodePtr = &at(valueSource.nodeIndex());
1301         if (!nodePtr->shouldGenerate()) {
1302             // It's legitimately dead. As in, nobody will ever use this node, or operand,
1303             // ever. Set it to Undefined to make the GC happy after the OSR.
1304             return ValueRecovery::constant(jsUndefined());
1305         }
1306     
1307         GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1308         if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
1309             // Try to see if there is an alternate node that would contain the value we want.
1310             // There are four possibilities:
1311             //
1312             // ValueToInt32: If the only remaining live version of the value is
1313             //    ValueToInt32, then we can use it.
1314             //
1315             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
1316             //    then the only remaining uses are ones that want a properly formed number
1317             //    rather than a UInt32 intermediate.
1318             //
1319             // The reverse of the above: This node could be a UInt32ToNumber, but its
1320             //    alternative is still alive. This means that the only remaining uses of
1321             //    the number would be fine with a UInt32 intermediate.
1322         
1323             bool found = false;
1324         
1325             if (nodePtr->op() == UInt32ToNumber) {
1326                 NodeIndex nodeIndex = nodePtr->child1().index();
1327                 nodePtr = &at(nodeIndex);
1328                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1329                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
1330                     found = true;
1331             }
1332         
1333             if (!found) {
1334                 NodeIndex valueToInt32Index = NoNode;
1335                 NodeIndex uint32ToNumberIndex = NoNode;
1336             
1337                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
1338                     GenerationInfo& info = m_generationInfo[virtualRegister];
1339                     if (!info.alive())
1340                         continue;
1341                     if (info.nodeIndex() == NoNode)
1342                         continue;
1343                     Node& node = at(info.nodeIndex());
1344                     if (node.child1Unchecked() != valueSource.nodeIndex())
1345                         continue;
1346                     switch (node.op()) {
1347                     case ValueToInt32:
1348                         valueToInt32Index = info.nodeIndex();
1349                         break;
1350                     case UInt32ToNumber:
1351                         uint32ToNumberIndex = info.nodeIndex();
1352                         break;
1353                     default:
1354                         break;
1355                     }
1356                 }
1357             
1358                 NodeIndex nodeIndexToUse;
1359                 if (valueToInt32Index != NoNode)
1360                     nodeIndexToUse = valueToInt32Index;
1361                 else if (uint32ToNumberIndex != NoNode)
1362                     nodeIndexToUse = uint32ToNumberIndex;
1363                 else
1364                     nodeIndexToUse = NoNode;
1365             
1366                 if (nodeIndexToUse != NoNode) {
1367                     nodePtr = &at(nodeIndexToUse);
1368                     infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1369                     ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
1370                     found = true;
1371                 }
1372             }
1373         
1374             if (!found)
1375                 return ValueRecovery::constant(jsUndefined());
1376         }
1377     
1378         ASSERT(infoPtr->alive());
1379
1380         if (infoPtr->registerFormat() != DataFormatNone) {
1381             if (infoPtr->registerFormat() == DataFormatDouble)
1382                 return ValueRecovery::inFPR(infoPtr->fpr());
1383 #if USE(JSVALUE32_64)
1384             if (infoPtr->registerFormat() & DataFormatJS)
1385                 return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
1386 #endif
1387             return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
1388         }
1389         if (infoPtr->spillFormat() != DataFormatNone)
1390             return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()), infoPtr->spillFormat());
1391     
1392         ASSERT_NOT_REACHED();
1393         return ValueRecovery();
1394     }
1395         
1396     default:
1397         ASSERT_NOT_REACHED();
1398         return ValueRecovery();
1399     }
1400 }
1401
1402 void SpeculativeJIT::compileGetCharCodeAt(Node& node)
1403 {
1404     ASSERT(node.child3() == NoNode);
1405     SpeculateCellOperand string(this, node.child1());
1406     SpeculateStrictInt32Operand index(this, node.child2());
1407     StorageOperand storage(this, node.child3());
1408
1409     GPRReg stringReg = string.gpr();
1410     GPRReg indexReg = index.gpr();
1411     GPRReg storageReg = storage.gpr();
1412     
1413     if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
1414         ASSERT(!(at(node.child1()).prediction() & PredictString));
1415         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1416         noResult(m_compileIndex);
1417         return;
1418     }
1419
1420     // unsigned comparison so we can filter out negative indices and indices that are too large
1421     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
1422
1423     GPRTemporary scratch(this);
1424     GPRReg scratchReg = scratch.gpr();
1425
1426     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
1427
1428     // Load the character into scratchReg
1429     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1430
1431     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
1432     JITCompiler::Jump cont8Bit = m_jit.jump();
1433
1434     is16Bit.link(&m_jit);
1435
1436     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
1437
1438     cont8Bit.link(&m_jit);
1439
1440     integerResult(scratchReg, m_compileIndex);
1441 }
1442
1443 void SpeculativeJIT::compileGetByValOnString(Node& node)
1444 {
1445     SpeculateCellOperand base(this, node.child1());
1446     SpeculateStrictInt32Operand property(this, node.child2());
1447     StorageOperand storage(this, node.child3());
1448     GPRReg baseReg = base.gpr();
1449     GPRReg propertyReg = property.gpr();
1450     GPRReg storageReg = storage.gpr();
1451
1452     if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
1453         ASSERT(!(at(node.child1()).prediction() & PredictString));
1454         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1455         noResult(m_compileIndex);
1456         return;
1457     }
1458
1459     // unsigned comparison so we can filter out negative indices and indices that are too large
1460     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
1461
1462     GPRTemporary scratch(this);
1463     GPRReg scratchReg = scratch.gpr();
1464
1465     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
1466
1467     // Load the character into scratchReg
1468     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1469
1470     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
1471     JITCompiler::Jump cont8Bit = m_jit.jump();
1472
1473     is16Bit.link(&m_jit);
1474
1475     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
1476
1477     // We only support ascii characters
1478     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
1479
1480     // 8 bit string values don't need the isASCII check.
1481     cont8Bit.link(&m_jit);
1482
1483     GPRTemporary smallStrings(this);
1484     GPRReg smallStringsReg = smallStrings.gpr();
1485     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalData()->smallStrings.singleCharacterStrings()), smallStringsReg);
1486     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
1487     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
1488     cellResult(scratchReg, m_compileIndex);
1489 }
1490
1491 void SpeculativeJIT::compileValueToInt32(Node& node)
1492 {
1493     if (at(node.child1()).shouldSpeculateInteger()) {
1494         SpeculateIntegerOperand op1(this, node.child1());
1495         GPRTemporary result(this, op1);
1496         m_jit.move(op1.gpr(), result.gpr());
1497         integerResult(result.gpr(), m_compileIndex, op1.format());
1498         return;
1499     }
1500     
1501     if (at(node.child1()).shouldSpeculateNumber()) {
1502         SpeculateDoubleOperand op1(this, node.child1());
1503         GPRTemporary result(this);
1504         FPRReg fpr = op1.fpr();
1505         GPRReg gpr = result.gpr();
1506         JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
1507         
1508         silentSpillAllRegisters(gpr);
1509         callOperation(toInt32, gpr, fpr);
1510         silentFillAllRegisters(gpr);
1511         
1512         truncatedToInteger.link(&m_jit);
1513         integerResult(gpr, m_compileIndex);
1514         return;
1515     }
1516     
1517     if (at(node.child1()).shouldSpeculateBoolean()) {
1518         SpeculateBooleanOperand op1(this, node.child1());
1519         GPRTemporary result(this, op1);
1520         
1521         m_jit.and32(JITCompiler::TrustedImm32(1), op1.gpr());
1522         
1523         integerResult(op1.gpr(), m_compileIndex);
1524         return;
1525     }
1526     
1527     // Do it the safe way.
1528     nonSpeculativeValueToInt32(node);
1529     return;
1530 }
1531
1532 void SpeculativeJIT::compileUInt32ToNumber(Node& node)
1533 {
1534     if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
1535         // We know that this sometimes produces doubles. So produce a double every
1536         // time. This at least allows subsequent code to not have weird conditionals.
1537             
1538         IntegerOperand op1(this, node.child1());
1539         FPRTemporary result(this);
1540             
1541         GPRReg inputGPR = op1.gpr();
1542         FPRReg outputFPR = result.fpr();
1543             
1544         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
1545             
1546         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
1547         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
1548         positive.link(&m_jit);
1549             
1550         doubleResult(outputFPR, m_compileIndex);
1551         return;
1552     }
1553
1554     IntegerOperand op1(this, node.child1());
1555     GPRTemporary result(this, op1);
1556
1557     // Test the operand is positive. This is a very special speculation check - we actually
1558     // use roll-forward speculation here, where if this fails, we jump to the baseline
1559     // instruction that follows us, rather than the one we're executing right now. We have
1560     // to do this because by this point, the original values necessary to compile whatever
1561     // operation the UInt32ToNumber originated from might be dead.
1562     forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(op1.gpr()));
1563
1564     m_jit.move(op1.gpr(), result.gpr());
1565     integerResult(result.gpr(), m_compileIndex, op1.format());
1566 }
1567
1568 static double clampDoubleToByte(double d)
1569 {
1570     d += 0.5;
1571     if (!(d > 0))
1572         d = 0;
1573     else if (d > 255)
1574         d = 255;
1575     return d;
1576 }
1577
1578 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
1579 {
1580     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
1581     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
1582     jit.xorPtr(result, result);
1583     MacroAssembler::Jump clamped = jit.jump();
1584     tooBig.link(&jit);
1585     jit.move(JITCompiler::TrustedImm32(255), result);
1586     clamped.link(&jit);
1587     inBounds.link(&jit);
1588 }
1589
1590 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
1591 {
1592     // Unordered compare so we pick up NaN
1593     static const double zero = 0;
1594     static const double byteMax = 255;
1595     static const double half = 0.5;
1596     jit.loadDouble(&zero, scratch);
1597     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
1598     jit.loadDouble(&byteMax, scratch);
1599     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
1600     
1601     jit.loadDouble(&half, scratch);
1602     // FIXME: This should probably just use a floating point round!
1603     // https://bugs.webkit.org/show_bug.cgi?id=72054
1604     jit.addDouble(source, scratch);
1605     jit.truncateDoubleToInt32(scratch, result);   
1606     MacroAssembler::Jump truncatedInt = jit.jump();
1607     
1608     tooSmall.link(&jit);
1609     jit.xorPtr(result, result);
1610     MacroAssembler::Jump zeroed = jit.jump();
1611     
1612     tooBig.link(&jit);
1613     jit.move(JITCompiler::TrustedImm32(255), result);
1614     
1615     truncatedInt.link(&jit);
1616     zeroed.link(&jit);
1617
1618 }
1619
1620 void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node)
1621 {
1622     Edge baseUse = node.child1();
1623     Edge valueUse = node.child3();
1624     
1625     if (!isByteArrayPrediction(m_state.forNode(baseUse).m_type))
1626         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1627     GPRTemporary value;
1628     GPRReg valueGPR;
1629
1630     if (at(valueUse).isConstant()) {
1631         JSValue jsValue = valueOfJSConstant(valueUse.index());
1632         if (!jsValue.isNumber()) {
1633             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1634             noResult(m_compileIndex);
1635             return;
1636         }
1637         int clampedValue = clampDoubleToByte(jsValue.asNumber());
1638         GPRTemporary scratch(this);
1639         GPRReg scratchReg = scratch.gpr();
1640         m_jit.move(Imm32(clampedValue), scratchReg);
1641         value.adopt(scratch);
1642         valueGPR = scratchReg;
1643     } else if (!at(valueUse).shouldNotSpeculateInteger()) {
1644         SpeculateIntegerOperand valueOp(this, valueUse);
1645         GPRTemporary scratch(this);
1646         GPRReg scratchReg = scratch.gpr();
1647         m_jit.move(valueOp.gpr(), scratchReg);
1648         compileClampIntegerToByte(m_jit, scratchReg);
1649         value.adopt(scratch);
1650         valueGPR = scratchReg;
1651     } else {
1652         SpeculateDoubleOperand valueOp(this, valueUse);
1653         GPRTemporary result(this);
1654         FPRTemporary floatScratch(this);
1655         FPRReg fpr = valueOp.fpr();
1656         GPRReg gpr = result.gpr();
1657         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
1658         value.adopt(result);
1659         valueGPR = gpr;
1660     }
1661     ASSERT_UNUSED(valueGPR, valueGPR != property);
1662     ASSERT(valueGPR != base);
1663     GPRTemporary storage(this);
1664     GPRReg storageReg = storage.gpr();
1665     ASSERT(valueGPR != storageReg);
1666     m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg);
1667     MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize()));
1668     m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData()));
1669     outOfBounds.link(&m_jit);
1670     noResult(m_compileIndex);
1671 }
1672
1673 void SpeculativeJIT::compileGetByValOnByteArray(Node& node)
1674 {
1675     SpeculateCellOperand base(this, node.child1());
1676     SpeculateStrictInt32Operand property(this, node.child2());
1677
1678     GPRReg baseReg = base.gpr();
1679     GPRReg propertyReg = property.gpr();
1680
1681     if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) {
1682         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1683         noResult(m_compileIndex);
1684         return;
1685     }
1686
1687     // Load the character into scratchReg
1688     GPRTemporary storage(this);
1689     GPRReg storageReg = storage.gpr();
1690     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
1691     
1692     // unsigned comparison so we can filter out negative indices and indices that are too large
1693     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())));
1694
1695     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, ByteArray::offsetOfData()), storageReg);
1696     integerResult(storageReg, m_compileIndex);
1697 }
1698
1699 void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck)
1700 {
1701     SpeculateCellOperand base(this, node.child1());
1702     GPRTemporary result(this);
1703     
1704     GPRReg baseGPR = base.gpr();
1705     GPRReg resultGPR = result.gpr();
1706     
1707     if (needsSpeculationCheck)
1708         speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1709     
1710     m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
1711     
1712     integerResult(resultGPR, m_compileIndex);
1713 }
1714
1715 void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
1716 {
1717     SpeculateCellOperand base(this, node.child1());
1718     SpeculateStrictInt32Operand property(this, node.child2());
1719     StorageOperand storage(this, node.child3());
1720
1721     GPRReg baseReg = base.gpr();
1722     GPRReg propertyReg = property.gpr();
1723     GPRReg storageReg = storage.gpr();
1724
1725     GPRTemporary result(this);
1726     GPRReg resultReg = result.gpr();
1727
1728     if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
1729         ASSERT_NOT_REACHED();
1730         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1731         noResult(m_compileIndex);
1732         return;
1733     }
1734
1735     MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
1736     m_jit.xorPtr(resultReg, resultReg);
1737     MacroAssembler::Jump outOfBounds = m_jit.jump();
1738     inBounds.link(&m_jit);
1739     switch (elementSize) {
1740     case 1:
1741         if (signedness == SignedTypedArray)
1742             m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
1743         else
1744             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
1745         break;
1746     case 2:
1747         if (signedness == SignedTypedArray)
1748             m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
1749         else
1750             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
1751         break;
1752     case 4:
1753         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
1754         break;
1755     default:
1756         ASSERT_NOT_REACHED();
1757     }
1758     outOfBounds.link(&m_jit);
1759     if (elementSize < 4 || signedness == SignedTypedArray) {
1760         integerResult(resultReg, m_compileIndex);
1761         return;
1762     }
1763     
1764     ASSERT(elementSize == 4 && signedness == UnsignedTypedArray);
1765     if (node.shouldSpeculateInteger()) {
1766         forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)), ValueRecovery::uint32InGPR(resultReg));
1767         integerResult(resultReg, m_compileIndex);
1768         return;
1769     }
1770     
1771     FPRTemporary fresult(this);
1772     m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
1773     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
1774     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
1775     positive.link(&m_jit);
1776     doubleResult(fresult.fpr(), m_compileIndex);
1777 }
1778
1779 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding)
1780 {
1781     Edge baseUse = node.child1();
1782     Edge valueUse = node.child3();
1783     
1784     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
1785         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1786     GPRTemporary value;
1787     GPRReg valueGPR;
1788     
1789     if (at(valueUse).isConstant()) {
1790         JSValue jsValue = valueOfJSConstant(valueUse.index());
1791         if (!jsValue.isNumber()) {
1792             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1793             noResult(m_compileIndex);
1794             return;
1795         }
1796         double d = jsValue.asNumber();
1797         if (rounding == ClampRounding) {
1798             ASSERT(elementSize == 1);
1799             d = clampDoubleToByte(d);
1800         }
1801         GPRTemporary scratch(this);
1802         GPRReg scratchReg = scratch.gpr();
1803         m_jit.move(Imm32(static_cast<int>(d)), scratchReg);
1804         value.adopt(scratch);
1805         valueGPR = scratchReg;
1806     } else if (!at(valueUse).shouldNotSpeculateInteger()) {
1807         SpeculateIntegerOperand valueOp(this, valueUse);
1808         GPRTemporary scratch(this);
1809         GPRReg scratchReg = scratch.gpr();
1810         m_jit.move(valueOp.gpr(), scratchReg);
1811         if (rounding == ClampRounding) {
1812             ASSERT(elementSize == 1);
1813             compileClampIntegerToByte(m_jit, scratchReg);
1814         }
1815         value.adopt(scratch);
1816         valueGPR = scratchReg;
1817     } else if (rounding == ClampRounding) {
1818         ASSERT(elementSize == 1);
1819         SpeculateDoubleOperand valueOp(this, valueUse);
1820         GPRTemporary result(this);
1821         FPRTemporary floatScratch(this);
1822         FPRReg fpr = valueOp.fpr();
1823         GPRReg gpr = result.gpr();
1824         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
1825         value.adopt(result);
1826         valueGPR = gpr;
1827     } else {
1828         SpeculateDoubleOperand valueOp(this, valueUse);
1829         GPRTemporary result(this);
1830         FPRReg fpr = valueOp.fpr();
1831         GPRReg gpr = result.gpr();
1832         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
1833         m_jit.xorPtr(gpr, gpr);
1834         MacroAssembler::Jump fixed = m_jit.jump();
1835         notNaN.link(&m_jit);
1836
1837         MacroAssembler::Jump done;
1838         if (signedness == SignedTypedArray)
1839             done = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
1840         else
1841             done = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
1842
1843         silentSpillAllRegisters(gpr);
1844         callOperation(toInt32, gpr, fpr);
1845         silentFillAllRegisters(gpr);
1846
1847         done.link(&m_jit);
1848         fixed.link(&m_jit);
1849         value.adopt(result);
1850         valueGPR = gpr;
1851     }
1852     ASSERT_UNUSED(valueGPR, valueGPR != property);
1853     ASSERT(valueGPR != base);
1854     GPRTemporary storage(this);
1855     GPRReg storageReg = storage.gpr();
1856     ASSERT(valueGPR != storageReg);
1857     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
1858     MacroAssembler::Jump outOfBounds;
1859     if (speculationRequirements != NoTypedArraySpecCheck)
1860         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
1861
1862     switch (elementSize) {
1863     case 1:
1864         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
1865         break;
1866     case 2:
1867         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
1868         break;
1869     case 4:
1870         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
1871         break;
1872     default:
1873         ASSERT_NOT_REACHED();
1874     }
1875     if (speculationRequirements != NoTypedArraySpecCheck)
1876         outOfBounds.link(&m_jit);
1877     noResult(m_compileIndex);
1878 }
1879
1880 void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
1881 {
1882     SpeculateCellOperand base(this, node.child1());
1883     SpeculateStrictInt32Operand property(this, node.child2());
1884     StorageOperand storage(this, node.child3());
1885
1886     GPRReg baseReg = base.gpr();
1887     GPRReg propertyReg = property.gpr();
1888     GPRReg storageReg = storage.gpr();
1889     
1890     if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
1891         ASSERT_NOT_REACHED();
1892         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1893         noResult(m_compileIndex);
1894         return;
1895     }
1896
1897     FPRTemporary result(this);
1898     FPRReg resultReg = result.fpr();
1899     ASSERT(speculationRequirements != NoTypedArraySpecCheck);
1900     MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
1901     static const double zero = 0;
1902     m_jit.loadDouble(&zero, resultReg);
1903     MacroAssembler::Jump outOfBounds = m_jit.jump();
1904     inBounds.link(&m_jit);
1905     switch (elementSize) {
1906     case 4:
1907         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
1908         m_jit.convertFloatToDouble(resultReg, resultReg);
1909         break;
1910     case 8: {
1911         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
1912         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
1913         static const double NaN = std::numeric_limits<double>::quiet_NaN();
1914         m_jit.loadDouble(&NaN, resultReg);
1915         notNaN.link(&m_jit);
1916         break;
1917     }
1918     default:
1919         ASSERT_NOT_REACHED();
1920     }
1921     outOfBounds.link(&m_jit);
1922     doubleResult(resultReg, m_compileIndex);
1923 }
1924
1925 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
1926 {
1927     Edge baseUse = node.child1();
1928     Edge valueUse = node.child3();
1929     
1930     SpeculateDoubleOperand valueOp(this, valueUse);
1931     
1932     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
1933         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1934     
1935     GPRTemporary result(this);
1936     
1937     GPRTemporary storage(this);
1938     GPRReg storageReg = storage.gpr();
1939     
1940     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
1941     MacroAssembler::Jump outOfBounds;
1942     if (speculationRequirements != NoTypedArraySpecCheck)
1943         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
1944     
1945     switch (elementSize) {
1946     case 4: {
1947         FPRTemporary scratch(this);
1948         m_jit.moveDouble(valueOp.fpr(), scratch.fpr());
1949         m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr());
1950         m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
1951         break;
1952     }
1953     case 8:
1954         m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
1955         break;
1956     default:
1957         ASSERT_NOT_REACHED();
1958     }
1959     if (speculationRequirements != NoTypedArraySpecCheck)
1960         outOfBounds.link(&m_jit);
1961     noResult(m_compileIndex);
1962 }
1963
1964 void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
1965 {
1966     // Check that prototype is an object.
1967     m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
1968     speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branchIfNotObject(scratchReg));
1969     
1970     // Initialize scratchReg with the value being checked.
1971     m_jit.move(valueReg, scratchReg);
1972     
1973     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
1974     MacroAssembler::Label loop(&m_jit);
1975     m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
1976 #if USE(JSVALUE64)
1977     m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
1978 #else
1979     m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
1980 #endif
1981     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
1982 #if USE(JSVALUE64)
1983     m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
1984 #else
1985     m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
1986 #endif
1987     
1988     // No match - result is false.
1989 #if USE(JSVALUE64)
1990     m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
1991 #else
1992     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
1993 #endif
1994     MacroAssembler::Jump putResult = m_jit.jump();
1995     
1996     isInstance.link(&m_jit);
1997 #if USE(JSVALUE64)
1998     m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
1999 #else
2000     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
2001 #endif
2002     
2003     putResult.link(&m_jit);
2004 }
2005
2006 void SpeculativeJIT::compileInstanceOf(Node& node)
2007 {
2008     if (!!(at(node.child1()).prediction() & ~PredictCell) && !!(m_state.forNode(node.child1()).m_type & ~PredictCell)) {
2009         // It might not be a cell. Speculate less aggressively.
2010         
2011         JSValueOperand value(this, node.child1());
2012         SpeculateCellOperand prototype(this, node.child3());
2013         GPRTemporary scratch(this);
2014         
2015         GPRReg prototypeReg = prototype.gpr();
2016         GPRReg scratchReg = scratch.gpr();
2017         
2018 #if USE(JSVALUE64)
2019         GPRReg valueReg = value.gpr();
2020         MacroAssembler::Jump isCell = m_jit.branchTestPtr(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
2021         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
2022 #else
2023         GPRReg valueTagReg = value.tagGPR();
2024         GPRReg valueReg = value.payloadGPR();
2025         MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
2026         m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2027 #endif
2028
2029         MacroAssembler::Jump done = m_jit.jump();
2030         
2031         isCell.link(&m_jit);
2032         
2033         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2034         
2035         done.link(&m_jit);
2036
2037 #if USE(JSVALUE64)
2038         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2039 #else
2040         booleanResult(scratchReg, m_compileIndex);
2041 #endif
2042         return;
2043     }
2044     
2045     SpeculateCellOperand value(this, node.child1());
2046     // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
2047     SpeculateCellOperand prototype(this, node.child3());
2048     
2049     GPRTemporary scratch(this);
2050     
2051     GPRReg valueReg = value.gpr();
2052     GPRReg prototypeReg = prototype.gpr();
2053     GPRReg scratchReg = scratch.gpr();
2054     
2055     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2056
2057 #if USE(JSVALUE64)
2058     jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2059 #else
2060     booleanResult(scratchReg, m_compileIndex);
2061 #endif
2062 }
2063
2064 void SpeculativeJIT::compileSoftModulo(Node& node)
2065 {
2066     // In the fast path, the dividend value could be the final result
2067     // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
2068     SpeculateStrictInt32Operand op1(this, node.child1());
2069     if (isInt32Constant(node.child2().index())) {
2070         int32_t divisor = valueOfInt32Constant(node.child2().index());
2071 #if CPU(X86) || CPU(X86_64)
2072         if (divisor) {
2073             GPRReg op1Gpr = op1.gpr();
2074
2075             GPRTemporary eax(this, X86Registers::eax);
2076             GPRTemporary edx(this, X86Registers::edx);
2077             GPRTemporary scratch(this);
2078             GPRReg scratchGPR = scratch.gpr();
2079
2080             GPRReg op1SaveGPR;
2081             if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
2082                 op1SaveGPR = allocate();
2083                 ASSERT(op1Gpr != op1SaveGPR);
2084                 m_jit.move(op1Gpr, op1SaveGPR);
2085             } else
2086                 op1SaveGPR = op1Gpr;
2087             ASSERT(op1SaveGPR != X86Registers::eax);
2088             ASSERT(op1SaveGPR != X86Registers::edx);
2089
2090             m_jit.move(op1Gpr, eax.gpr());
2091             m_jit.move(TrustedImm32(divisor), scratchGPR);
2092             if (divisor == -1)
2093                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
2094             m_jit.assembler().cdq();
2095             m_jit.assembler().idivl_r(scratchGPR);
2096             // Check that we're not about to create negative zero.
2097             // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
2098             JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
2099             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
2100             numeratorPositive.link(&m_jit);
2101             
2102             if (op1SaveGPR != op1Gpr)
2103                 unlock(op1SaveGPR);
2104
2105             integerResult(edx.gpr(), m_compileIndex);
2106             return;
2107         }
2108 #endif
2109     }
2110
2111     SpeculateIntegerOperand op2(this, node.child2());
2112 #if CPU(X86) || CPU(X86_64)
2113     GPRTemporary eax(this, X86Registers::eax);
2114     GPRTemporary edx(this, X86Registers::edx);
2115     GPRReg op1GPR = op1.gpr();
2116     GPRReg op2GPR = op2.gpr();
2117     
2118     GPRReg op2TempGPR;
2119     GPRReg temp;
2120     GPRReg op1SaveGPR;
2121     
2122     if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
2123         op2TempGPR = allocate();
2124         temp = op2TempGPR;
2125     } else {
2126         op2TempGPR = InvalidGPRReg;
2127         if (op1GPR == X86Registers::eax)
2128             temp = X86Registers::edx;
2129         else
2130             temp = X86Registers::eax;
2131     }
2132     
2133     if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
2134         op1SaveGPR = allocate();
2135         ASSERT(op1GPR != op1SaveGPR);
2136         m_jit.move(op1GPR, op1SaveGPR);
2137     } else
2138         op1SaveGPR = op1GPR;
2139     
2140     ASSERT(temp != op1GPR);
2141     ASSERT(temp != op2GPR);
2142     ASSERT(op1SaveGPR != X86Registers::eax);
2143     ASSERT(op1SaveGPR != X86Registers::edx);
2144     
2145     m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
2146     
2147     JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
2148     
2149     JITCompiler::Jump done;
2150     // FIXME: if the node is not used as number then we can do this more easily.
2151     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
2152     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
2153     
2154     safeDenominator.link(&m_jit);
2155             
2156     if (op2TempGPR != InvalidGPRReg) {
2157         m_jit.move(op2GPR, op2TempGPR);
2158         op2GPR = op2TempGPR;
2159     }
2160             
2161     m_jit.move(op1GPR, eax.gpr());
2162     m_jit.assembler().cdq();
2163     m_jit.assembler().idivl_r(op2GPR);
2164             
2165     if (op2TempGPR != InvalidGPRReg)
2166         unlock(op2TempGPR);
2167
2168     // Check that we're not about to create negative zero.
2169     // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
2170     JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
2171     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
2172     numeratorPositive.link(&m_jit);
2173     
2174     if (op1SaveGPR != op1GPR)
2175         unlock(op1SaveGPR);
2176             
2177     integerResult(edx.gpr(), m_compileIndex);
2178 #else // CPU(X86) || CPU(X86_64) --> so not X86
2179     // Do this the *safest* way possible: call out to a C function that will do the modulo,
2180     // and then attempt to convert back.
2181     GPRReg op1GPR = op1.gpr();
2182     GPRReg op2GPR = op2.gpr();
2183     
2184     FPRResult result(this);
2185     
2186     flushRegisters();
2187     callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR);
2188     
2189     FPRTemporary scratch(this);
2190     GPRTemporary intResult(this);
2191     JITCompiler::JumpList failureCases;
2192     m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr());
2193     speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases);
2194     
2195     integerResult(intResult.gpr(), m_compileIndex);
2196 #endif // CPU(X86) || CPU(X86_64)
2197 }
2198
2199 void SpeculativeJIT::compileAdd(Node& node)
2200 {
2201     if (m_jit.graph().addShouldSpeculateInteger(node)) {
2202         if (isNumberConstant(node.child1().index())) {
2203             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2204             SpeculateIntegerOperand op2(this, node.child2());
2205             GPRTemporary result(this);
2206
2207             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2208                 m_jit.move(op2.gpr(), result.gpr());
2209                 m_jit.add32(Imm32(imm1), result.gpr());
2210             } else
2211                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
2212
2213             integerResult(result.gpr(), m_compileIndex);
2214             return;
2215         }
2216                 
2217         if (isNumberConstant(node.child2().index())) {
2218             SpeculateIntegerOperand op1(this, node.child1());
2219             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2220             GPRTemporary result(this);
2221                 
2222             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2223                 m_jit.move(op1.gpr(), result.gpr());
2224                 m_jit.add32(Imm32(imm2), result.gpr());
2225             } else
2226                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2227
2228             integerResult(result.gpr(), m_compileIndex);
2229             return;
2230         }
2231                 
2232         SpeculateIntegerOperand op1(this, node.child1());
2233         SpeculateIntegerOperand op2(this, node.child2());
2234         GPRTemporary result(this, op1, op2);
2235
2236         GPRReg gpr1 = op1.gpr();
2237         GPRReg gpr2 = op2.gpr();
2238         GPRReg gprResult = result.gpr();
2239
2240         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2241             if (gpr1 == gprResult)
2242                 m_jit.add32(gpr2, gprResult);
2243             else {
2244                 m_jit.move(gpr2, gprResult);
2245                 m_jit.add32(gpr1, gprResult);
2246             }
2247         } else {
2248             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
2249                 
2250             if (gpr1 == gprResult)
2251                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
2252             else if (gpr2 == gprResult)
2253                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
2254             else
2255                 speculationCheck(Overflow, JSValueRegs(), NoNode, check);
2256         }
2257
2258         integerResult(gprResult, m_compileIndex);
2259         return;
2260     }
2261         
2262     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2263         SpeculateDoubleOperand op1(this, node.child1());
2264         SpeculateDoubleOperand op2(this, node.child2());
2265         FPRTemporary result(this, op1, op2);
2266
2267         FPRReg reg1 = op1.fpr();
2268         FPRReg reg2 = op2.fpr();
2269         m_jit.addDouble(reg1, reg2, result.fpr());
2270
2271         doubleResult(result.fpr(), m_compileIndex);
2272         return;
2273     }
2274
2275     if (node.op() == ValueAdd) {
2276         compileValueAdd(node);
2277         return;
2278     }
2279     
2280     // We don't handle this yet. :-(
2281     terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2282 }
2283
2284 void SpeculativeJIT::compileArithSub(Node& node)
2285 {
2286     if (m_jit.graph().addShouldSpeculateInteger(node)) {
2287         if (isNumberConstant(node.child2().index())) {
2288             SpeculateIntegerOperand op1(this, node.child1());
2289             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2290             GPRTemporary result(this);
2291
2292             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2293                 m_jit.move(op1.gpr(), result.gpr());
2294                 m_jit.sub32(Imm32(imm2), result.gpr());
2295             } else {
2296 #if ENABLE(JIT_CONSTANT_BLINDING)
2297                 GPRTemporary scratch(this);
2298                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr(), scratch.gpr()));
2299 #else
2300                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2301 #endif
2302             }
2303
2304             integerResult(result.gpr(), m_compileIndex);
2305             return;
2306         }
2307             
2308         if (isNumberConstant(node.child1().index())) {
2309             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2310             SpeculateIntegerOperand op2(this, node.child2());
2311             GPRTemporary result(this);
2312                 
2313             m_jit.move(Imm32(imm1), result.gpr());
2314             if (nodeCanTruncateInteger(node.arithNodeFlags()))
2315                 m_jit.sub32(op2.gpr(), result.gpr());
2316             else
2317                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
2318                 
2319             integerResult(result.gpr(), m_compileIndex);
2320             return;
2321         }
2322             
2323         SpeculateIntegerOperand op1(this, node.child1());
2324         SpeculateIntegerOperand op2(this, node.child2());
2325         GPRTemporary result(this);
2326
2327         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2328             m_jit.move(op1.gpr(), result.gpr());
2329             m_jit.sub32(op2.gpr(), result.gpr());
2330         } else
2331             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
2332
2333         integerResult(result.gpr(), m_compileIndex);
2334         return;
2335     }
2336         
2337     SpeculateDoubleOperand op1(this, node.child1());
2338     SpeculateDoubleOperand op2(this, node.child2());
2339     FPRTemporary result(this, op1);
2340
2341     FPRReg reg1 = op1.fpr();
2342     FPRReg reg2 = op2.fpr();
2343     m_jit.subDouble(reg1, reg2, result.fpr());
2344
2345     doubleResult(result.fpr(), m_compileIndex);
2346 }
2347
2348 void SpeculativeJIT::compileArithNegate(Node& node)
2349 {
2350     if (m_jit.graph().negateShouldSpeculateInteger(node)) {
2351         SpeculateIntegerOperand op1(this, node.child1());
2352         GPRTemporary result(this);
2353
2354         m_jit.move(op1.gpr(), result.gpr());
2355
2356         if (nodeCanTruncateInteger(node.arithNodeFlags()))
2357             m_jit.neg32(result.gpr());
2358         else {
2359             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
2360             if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags()))
2361                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
2362         }
2363
2364         integerResult(result.gpr(), m_compileIndex);
2365         return;
2366     }
2367         
2368     SpeculateDoubleOperand op1(this, node.child1());
2369     FPRTemporary result(this);
2370
2371     m_jit.negateDouble(op1.fpr(), result.fpr());
2372
2373     doubleResult(result.fpr(), m_compileIndex);
2374 }
2375
2376 void SpeculativeJIT::compileArithMul(Node& node)
2377 {
2378     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2379         SpeculateIntegerOperand op1(this, node.child1());
2380         SpeculateIntegerOperand op2(this, node.child2());
2381         GPRTemporary result(this);
2382
2383         GPRReg reg1 = op1.gpr();
2384         GPRReg reg2 = op2.gpr();
2385
2386         // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
2387         // here. A multiply on integers performed in the double domain and then truncated to
2388         // an integer will give a different result than a multiply performed in the integer
2389         // domain and then truncated, if the integer domain result would have resulted in
2390         // something bigger than what a 32-bit integer can hold. JavaScript mandates that
2391         // the semantics are always as if the multiply had been performed in the double
2392         // domain.
2393             
2394         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
2395             
2396         // Check for negative zero, if the users of this node care about such things.
2397         if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
2398             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
2399             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
2400             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
2401             resultNonZero.link(&m_jit);
2402         }
2403
2404         integerResult(result.gpr(), m_compileIndex);
2405         return;
2406     }
2407
2408     SpeculateDoubleOperand op1(this, node.child1());
2409     SpeculateDoubleOperand op2(this, node.child2());
2410     FPRTemporary result(this, op1, op2);
2411
2412     FPRReg reg1 = op1.fpr();
2413     FPRReg reg2 = op2.fpr();
2414         
2415     m_jit.mulDouble(reg1, reg2, result.fpr());
2416         
2417     doubleResult(result.fpr(), m_compileIndex);
2418 }
2419
2420 #if CPU(X86) || CPU(X86_64)
2421 void SpeculativeJIT::compileIntegerArithDivForX86(Node& node)
2422 {
2423     SpeculateIntegerOperand op1(this, node.child1());
2424     SpeculateIntegerOperand op2(this, node.child2());
2425     GPRTemporary eax(this, X86Registers::eax);
2426     GPRTemporary edx(this, X86Registers::edx);
2427     GPRReg op1GPR = op1.gpr();
2428     GPRReg op2GPR = op2.gpr();
2429     
2430     GPRReg op2TempGPR;
2431     GPRReg temp;
2432     if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
2433         op2TempGPR = allocate();
2434         temp = op2TempGPR;
2435     } else {
2436         op2TempGPR = InvalidGPRReg;
2437         if (op1GPR == X86Registers::eax)
2438             temp = X86Registers::edx;
2439         else
2440             temp = X86Registers::eax;
2441     }
2442     
2443     ASSERT(temp != op1GPR);
2444     ASSERT(temp != op2GPR);
2445     
2446     m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
2447     
2448     JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
2449     
2450     JITCompiler::Jump done;
2451     if (nodeUsedAsNumber(node.arithNodeFlags())) {
2452         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
2453         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
2454     } else {
2455         JITCompiler::Jump zero = m_jit.branchTest32(JITCompiler::Zero, op2GPR);
2456         JITCompiler::Jump notNeg2ToThe31 = m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1));
2457         zero.link(&m_jit);
2458         m_jit.move(TrustedImm32(0), eax.gpr());
2459         done = m_jit.jump();
2460         notNeg2ToThe31.link(&m_jit);
2461     }
2462     
2463     safeDenominator.link(&m_jit);
2464             
2465     // If the user cares about negative zero, then speculate that we're not about
2466     // to produce negative zero.
2467     if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
2468         MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
2469         speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
2470         numeratorNonZero.link(&m_jit);
2471     }
2472     
2473     if (op2TempGPR != InvalidGPRReg) {
2474         m_jit.move(op2GPR, op2TempGPR);
2475         op2GPR = op2TempGPR;
2476     }
2477             
2478     m_jit.move(op1GPR, eax.gpr());
2479     m_jit.assembler().cdq();
2480     m_jit.assembler().idivl_r(op2GPR);
2481             
2482     if (op2TempGPR != InvalidGPRReg)
2483         unlock(op2TempGPR);
2484
2485     // Check that there was no remainder. If there had been, then we'd be obligated to
2486     // produce a double result instead.
2487     if (nodeUsedAsNumber(node.arithNodeFlags()))
2488         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
2489     else
2490         done.link(&m_jit);
2491             
2492     integerResult(eax.gpr(), m_compileIndex);
2493 }
2494 #endif // CPU(X86) || CPU(X86_64)
2495
2496 void SpeculativeJIT::compileArithMod(Node& node)
2497 {
2498     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))
2499         && node.canSpeculateInteger()) {
2500         compileSoftModulo(node);
2501         return;
2502     }
2503         
2504     SpeculateDoubleOperand op1(this, node.child1());
2505     SpeculateDoubleOperand op2(this, node.child2());
2506         
2507     FPRReg op1FPR = op1.fpr();
2508     FPRReg op2FPR = op2.fpr();
2509         
2510     flushRegisters();
2511         
2512     FPRResult result(this);
2513
2514     callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR);
2515         
2516     doubleResult(result.fpr(), m_compileIndex);
2517 }
2518
2519 // Returns true if the compare is fused with a subsequent branch.
2520 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
2521 {
2522     if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
2523         return true;
2524
2525     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
2526         compileIntegerCompare(node, condition);
2527     else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
2528         compileDoubleCompare(node, doubleCondition);
2529     else if (node.op() == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
2530         compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
2531     else if (node.op() == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
2532         compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
2533     else
2534         nonSpeculativeNonPeepholeCompare(node, condition, operation);
2535     
2536     return false;
2537 }
2538
2539 bool SpeculativeJIT::compileStrictEqForConstant(Node& node, Edge value, JSValue constant)
2540 {
2541     JSValueOperand op1(this, value);
2542     
2543     unsigned branchIndexInBlock = detectPeepHoleBranch();
2544     if (branchIndexInBlock != UINT_MAX) {
2545         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
2546         Node& branchNode = at(branchNodeIndex);
2547         BlockIndex taken = branchNode.takenBlockIndex();
2548         BlockIndex notTaken = branchNode.notTakenBlockIndex();
2549         MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
2550         
2551         // The branch instruction will branch to the taken block.
2552         // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
2553         if (taken == (m_block + 1)) {
2554             condition = MacroAssembler::NotEqual;
2555             BlockIndex tmp = taken;
2556             taken = notTaken;
2557             notTaken = tmp;
2558         }
2559
2560 #if USE(JSVALUE64)
2561         branchPtr(condition, op1.gpr(), MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))), taken);
2562 #else
2563         GPRReg payloadGPR = op1.payloadGPR();
2564         GPRReg tagGPR = op1.tagGPR();
2565         if (condition == MacroAssembler::Equal) {
2566             // Drop down if not equal, go elsewhere if equal.
2567             MacroAssembler::Jump notEqual = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()));
2568             branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
2569             notEqual.link(&m_jit);
2570         } else {
2571             // Drop down if equal, go elsehwere if not equal.
2572             branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()), taken);
2573             branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
2574         }
2575 #endif
2576         
2577         jump(notTaken);
2578         
2579         use(node.child1());
2580         use(node.child2());
2581         m_indexInBlock = branchIndexInBlock;
2582         m_compileIndex = branchNodeIndex;
2583         return true;
2584     }
2585     
2586     GPRTemporary result(this);
2587     
2588 #if USE(JSVALUE64)
2589     GPRReg op1GPR = op1.gpr();
2590     GPRReg resultGPR = result.gpr();
2591     m_jit.move(MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(ValueFalse)), resultGPR);
2592     MacroAssembler::Jump notEqual = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))));
2593     m_jit.or32(MacroAssembler::TrustedImm32(1), resultGPR);
2594     notEqual.link(&m_jit);
2595     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
2596 #else
2597     GPRReg op1PayloadGPR = op1.payloadGPR();
2598     GPRReg op1TagGPR = op1.tagGPR();
2599     GPRReg resultGPR = result.gpr();
2600     m_jit.move(TrustedImm32(0), resultGPR);
2601     MacroAssembler::JumpList notEqual;
2602     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag())));
2603     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload())));
2604     m_jit.move(TrustedImm32(1), resultGPR);
2605     notEqual.link(&m_jit);
2606     booleanResult(resultGPR, m_compileIndex);
2607 #endif
2608     
2609     return false;
2610 }
2611
2612 bool SpeculativeJIT::compileStrictEq(Node& node)
2613 {
2614     // 1) If either operand is a constant and that constant is not a double, integer,
2615     //    or string, then do a JSValue comparison.
2616     
2617     if (isJSConstant(node.child1().index())) {
2618         JSValue value = valueOfJSConstant(node.child1().index());
2619         if (!value.isNumber() && !value.isString())
2620             return compileStrictEqForConstant(node, node.child2(), value);
2621     }
2622     
2623     if (isJSConstant(node.child2().index())) {
2624         JSValue value = valueOfJSConstant(node.child2().index());
2625         if (!value.isNumber() && !value.isString())
2626             return compileStrictEqForConstant(node, node.child1(), value);
2627     }
2628     
2629     // 2) If the operands are predicted integer, do an integer comparison.
2630     
2631     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
2632         unsigned branchIndexInBlock = detectPeepHoleBranch();
2633         if (branchIndexInBlock != UINT_MAX) {
2634             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
2635             compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal);
2636             use(node.child1());
2637             use(node.child2());
2638             m_indexInBlock = branchIndexInBlock;
2639             m_compileIndex = branchNodeIndex;
2640             return true;
2641         }
2642         compileIntegerCompare(node, MacroAssembler::Equal);
2643         return false;
2644     }
2645     
2646     // 3) If the operands are predicted double, do a double comparison.
2647     
2648     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2649         unsigned branchIndexInBlock = detectPeepHoleBranch();
2650         if (branchIndexInBlock != UINT_MAX) {
2651             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
2652             compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual);
2653             use(node.child1());
2654             use(node.child2());
2655             m_indexInBlock = branchIndexInBlock;
2656             m_compileIndex = branchNodeIndex;
2657             return true;
2658         }
2659         compileDoubleCompare(node, MacroAssembler::DoubleEqual);
2660         return false;
2661     }
2662     
2663     // 4) If the operands are predicted final object or array, then do a final object
2664     //    or array comparison.
2665     
2666     if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
2667         unsigned branchIndexInBlock = detectPeepHoleBranch();
2668         if (branchIndexInBlock != UINT_MAX) {
2669             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
2670             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
2671             use(node.child1());
2672             use(node.child2());
2673             m_indexInBlock = branchIndexInBlock;
2674             m_compileIndex = branchNodeIndex;
2675             return true;
2676         }
2677         compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
2678         return false;
2679     }
2680     
2681     if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
2682         unsigned branchIndexInBlock = detectPeepHoleBranch();
2683         if (branchIndexInBlock != UINT_MAX) {
2684             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
2685             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
2686             use(node.child1());
2687             use(node.child2());
2688             m_indexInBlock = branchIndexInBlock;
2689             m_compileIndex = branchNodeIndex;
2690             return true;
2691         }
2692         compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
2693         return false;
2694     }
2695     
2696     // 5) Fall back to non-speculative strict equality.
2697     
2698     return nonSpeculativeStrictEq(node);
2699 }
2700
2701 void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
2702 {
2703     if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
2704         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2705         return;
2706     }
2707         
2708     SpeculateCellOperand base(this, node.child1());
2709     GPRReg baseReg = base.gpr();
2710     
2711     PredictedType basePrediction = at(node.child2()).prediction();
2712     if (!(basePrediction & PredictInt32) && basePrediction) {
2713         ASSERT_NOT_REACHED();
2714         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2715         noResult(m_compileIndex);
2716         return;
2717     }
2718     
2719     GPRTemporary storage(this);
2720     GPRReg storageReg = storage.gpr();
2721     if (at(node.child1()).prediction() == PredictString) {
2722         if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
2723             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
2724
2725         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
2726         
2727         // Speculate that we're not accessing a rope
2728         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg));
2729
2730         m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
2731     } else if (at(node.child1()).shouldSpeculateByteArray()) {
2732         if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
2733             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
2734         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
2735     } else if (at(node.child1()).shouldSpeculateInt8Array()) {
2736         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
2737         if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
2738             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2739         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2740     } else if (at(node.child1()).shouldSpeculateInt16Array()) {
2741         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
2742         if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
2743             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2744         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2745     } else if (at(node.child1()).shouldSpeculateInt32Array()) {
2746         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
2747         if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2748             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2749         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2750     } else if (at(node.child1()).shouldSpeculateUint8Array()) {
2751         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
2752         if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
2753             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2754         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2755     } else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
2756         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
2757         if (!isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type))
2758             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2759         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2760     } else if (at(node.child1()).shouldSpeculateUint16Array()) {
2761         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
2762         if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
2763             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2764         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2765     } else if (at(node.child1()).shouldSpeculateUint32Array()) {
2766         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
2767         if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2768             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2769         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2770     } else if (at(node.child1()).shouldSpeculateFloat32Array()) {
2771         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
2772         if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2773             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2774         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2775     } else if (at(node.child1()).shouldSpeculateFloat64Array()) {
2776         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
2777         if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
2778             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2779         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2780     } else {
2781         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2782             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2783         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2784     }
2785     storageResult(storageReg, m_compileIndex);
2786 }
2787
2788 void SpeculativeJIT::compileNewFunctionNoCheck(Node& node)
2789 {
2790     GPRResult result(this);
2791     GPRReg resultGPR = result.gpr();
2792     flushRegisters();
2793     callOperation(
2794         operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
2795     cellResult(resultGPR, m_compileIndex);
2796 }
2797
2798 void SpeculativeJIT::compileNewFunctionExpression(Node& node)
2799 {
2800     GPRResult result(this);
2801     GPRReg resultGPR = result.gpr();
2802     flushRegisters();
2803     callOperation(
2804         operationNewFunctionExpression,
2805         resultGPR,
2806         m_jit.codeBlock()->functionExpr(node.functionExprIndex()));
2807     cellResult(resultGPR, m_compileIndex);
2808 }
2809
2810 bool SpeculativeJIT::compileRegExpExec(Node& node)
2811 {
2812     unsigned branchIndexInBlock = detectPeepHoleBranch();
2813     if (branchIndexInBlock == UINT_MAX)
2814         return false;
2815     NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
2816     ASSERT(node.adjustedRefCount() == 1);
2817
2818     Node& branchNode = at(branchNodeIndex);
2819     BlockIndex taken = branchNode.takenBlockIndex();
2820     BlockIndex notTaken = branchNode.notTakenBlockIndex();
2821     
2822     bool invert = false;
2823     if (taken == (m_block + 1)) {
2824         invert = true;
2825         BlockIndex tmp = taken;
2826         taken = notTaken;
2827         notTaken = tmp;
2828     }
2829
2830     SpeculateCellOperand base(this, node.child1());
2831     SpeculateCellOperand argument(this, node.child2());
2832     GPRReg baseGPR = base.gpr();
2833     GPRReg argumentGPR = argument.gpr();
2834     
2835     flushRegisters();
2836     GPRResult result(this);
2837     callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2838
2839     branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, result.gpr(), taken);
2840     jump(notTaken);
2841
2842     use(node.child1());
2843     use(node.child2());
2844     m_indexInBlock = branchIndexInBlock;
2845     m_compileIndex = branchNodeIndex;
2846
2847     return true;
2848 }
2849
2850 } } // namespace JSC::DFG
2851
2852 #endif